Make WordPress Core

Changeset 62194


Ignore:
Timestamp:
04/01/2026 04:37:48 PM (36 hours ago)
Author:
jorgefilipecosta
Message:

Connectors: Fix and generalize the API for custom connector types.

Validate setting_name, constant_name, and env_var_name in connector
registration — reject invalid values with _doing_it_wrong() instead of
silently falling back.
Change the auto-generated setting_name pattern from
connectors_ai_{$id}_api_key to connectors_{$type}_{$id}_api_key so it
works for any connector type. Built-in AI providers infer their names using
the existing connectors_ai_{$id}_api_key convention, preserving backward
compatibility.
Add constant_name and env_var_name as optional authentication fields,
allowing connectors to declare explicit PHP constant and environment
variable names for API key lookup. AI providers auto-generate these using
the {CONSTANT_CASE_ID}_API_KEY convention.
Refactor _wp_connectors_get_api_key_source() to accept explicit
env_var_name and constant_name parameters instead of deriving them from
the provider ID. Environment variable and constant checks are skipped when
not provided.
Generalize REST dispatch, settings registration, and script module data to
work with all connector types, not just ai_provider. Settings
registration skips already-registered settings. Non-AI connectors determine
isConnected based on key source.
Replace isInstalled with pluginFile in script module data output to fix
plugin entity ID resolution on the frontend.
Update PHPDoc to reflect current behavior — widen type from literal
'ai_provider' to non-empty-string, document new authentication fields,
and use Anthropic examples throughout.

Props gziolo, jorgefilipecosta.
Fixes #64957.

Location:
branches/7.0
Files:
5 edited
1 copied

Legend:

Unmodified
Added
Removed
  • branches/7.0

  • branches/7.0/src/wp-includes/class-wp-connector-registry.php

    r62116 r62194  
    3232 *     description: non-empty-string,
    3333 *     logo_url?: non-empty-string,
    34  *     type: 'ai_provider',
     34 *     type: non-empty-string,
    3535 *     authentication: array{
    3636 *         method: 'api_key'|'none',
    3737 *         credentials_url?: non-empty-string,
    38  *         setting_name?: non-empty-string
     38 *         setting_name?: non-empty-string,
     39 *         constant_name?: non-empty-string,
     40 *         env_var_name?: non-empty-string
    3941 *     },
    4042 *     plugin?: array{
     
    6769     *
    6870     * 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`, with hyphens in the ID
    71      * normalized to underscores (e.g., connector ID `openai` produces
    72      * `connectors_ai_openai_api_key`, and `azure-openai` produces
    73      * `connectors_ai_azure_openai_api_key`). This setting name is used for the Settings
    74      * API registration and REST API exposure.
     71     * For connectors with `api_key` authentication, a `setting_name` can be provided
     72     * explicitly. If omitted, one is automatically generated using the pattern
     73     * `connectors_{$type}_{$id}_api_key`, with hyphens in the type and ID normalized
     74     * to underscores (e.g., connector type `spam_filtering` with ID `akismet` produces
     75     * `connectors_spam_filtering_akismet_api_key`). This setting name is used for the
     76     * Settings API registration and REST API exposure.
    7577     *
    7678     * Registering a connector with an ID that is already registered will trigger a
     
    9092     *     @type string $description    Optional. The connector's description. Default empty string.
    9193     *     @type string $logo_url       Optional. URL to the connector's logo image.
    92      *     @type string $type           Required. The connector type. Currently, only 'ai_provider' is supported.
     94     *     @type string $type           Required. The connector type, e.g. 'ai_provider'.
    9395     *     @type array  $authentication {
    9496     *         Required. Authentication configuration.
     
    9698     *         @type string $method          Required. The authentication method: 'api_key' or 'none'.
    9799     *         @type string $credentials_url Optional. URL where users can obtain API credentials.
     100     *         @type string $setting_name    Optional. The setting name for the API key.
     101     *                                       When omitted, auto-generated as
     102     *                                       `connectors_{$type}_{$id}_api_key`.
     103     *                                       Must be a non-empty string when provided.
     104     *         @type string $constant_name   Optional. PHP constant name for the API key
     105     *                                       (e.g. 'ANTHROPIC_API_KEY'). Only checked when provided.
     106     *         @type string $env_var_name    Optional. Environment variable name for the API key
     107     *                                       (e.g. 'ANTHROPIC_API_KEY'). Only checked when provided.
    98108     *     }
    99109     *     @type array  $plugin         {
     
    193203                $connector['authentication']['credentials_url'] = $args['authentication']['credentials_url'];
    194204            }
    195             if ( ! empty( $args['authentication']['setting_name'] ) && is_string( $args['authentication']['setting_name'] ) ) {
     205            if ( isset( $args['authentication']['setting_name'] ) ) {
     206                if ( ! is_string( $args['authentication']['setting_name'] ) || '' === $args['authentication']['setting_name'] ) {
     207                    _doing_it_wrong(
     208                        __METHOD__,
     209                        /* translators: %s: Connector ID. */
     210                        sprintf( __( 'Connector "%s" authentication setting_name must be a non-empty string.' ), esc_html( $id ) ),
     211                        '7.0.0'
     212                    );
     213                    return null;
     214                }
    196215                $connector['authentication']['setting_name'] = $args['authentication']['setting_name'];
    197216            } else {
    198                 $connector['authentication']['setting_name'] = 'connectors_ai_' . str_replace( '-', '_', $id ) . '_api_key';
     217                $connector['authentication']['setting_name'] = str_replace( '-', '_', "connectors_{$connector['type']}_{$id}_api_key" );
     218            }
     219            if ( isset( $args['authentication']['constant_name'] ) ) {
     220                if ( ! is_string( $args['authentication']['constant_name'] ) || '' === $args['authentication']['constant_name'] ) {
     221                    _doing_it_wrong(
     222                        __METHOD__,
     223                        /* translators: %s: Connector ID. */
     224                        sprintf( __( 'Connector "%s" authentication constant_name must be a non-empty string.' ), esc_html( $id ) ),
     225                        '7.0.0'
     226                    );
     227                    return null;
     228                }
     229                $connector['authentication']['constant_name'] = $args['authentication']['constant_name'];
     230            }
     231            if ( isset( $args['authentication']['env_var_name'] ) ) {
     232                if ( ! is_string( $args['authentication']['env_var_name'] ) || '' === $args['authentication']['env_var_name'] ) {
     233                    _doing_it_wrong(
     234                        __METHOD__,
     235                        /* translators: %s: Connector ID. */
     236                        sprintf( __( 'Connector "%s" authentication env_var_name must be a non-empty string.' ), esc_html( $id ) ),
     237                        '7.0.0'
     238                    );
     239                    return null;
     240                }
     241                $connector['authentication']['env_var_name'] = $args['authentication']['env_var_name'];
    199242            }
    200243        }
  • branches/7.0/src/wp-includes/connectors.php

    r62067 r62194  
    4444 *     @type string $description    The connector's description.
    4545 *     @type string $logo_url       Optional. URL to the connector's logo image.
    46  *     @type string $type           The connector type. Currently, only 'ai_provider' is supported.
     46 *     @type string $type           The connector type, e.g. 'ai_provider'.
    4747 *     @type array  $authentication {
    4848 *         Authentication configuration. When method is 'api_key', includes
    49  *         credentials_url and setting_name. When 'none', only method is present.
     49 *         credentials_url, setting_name, and optionally constant_name and
     50 *         env_var_name. When 'none', only method is present.
    5051 *
    5152 *         @type string $method          The authentication method: 'api_key' or 'none'.
    5253 *         @type string $credentials_url Optional. URL where users can obtain API credentials.
    5354 *         @type string $setting_name    Optional. The setting name for the API key.
     55 *         @type string $constant_name   Optional. PHP constant name for the API key.
     56 *         @type string $env_var_name    Optional. Environment variable name for the API key.
    5457 *     }
    5558 *     @type array  $plugin         {
     
    6366 *     description: non-empty-string,
    6467 *     logo_url?: non-empty-string,
    65  *     type: 'ai_provider',
     68 *     type: non-empty-string,
    6669 *     authentication: array{
    6770 *         method: 'api_key'|'none',
    6871 *         credentials_url?: non-empty-string,
    69  *         setting_name?: non-empty-string
     72 *         setting_name?: non-empty-string,
     73 *         constant_name?: non-empty-string,
     74 *         env_var_name?: non-empty-string
    7075 *     },
    7176 *     plugin?: array{
     
    99104 *         @type string      $description    The connector's description.
    100105 *         @type string      $logo_url       Optional. URL to the connector's logo image.
    101  *         @type string      $type           The connector type. Currently, only 'ai_provider' is supported.
     106 *         @type string      $type           The connector type, e.g. 'ai_provider'.
    102107 *         @type array       $authentication {
    103108 *             Authentication configuration. When method is 'api_key', includes
    104  *             credentials_url and setting_name. When 'none', only method is present.
     109 *             credentials_url, setting_name, and optionally constant_name and
     110 *             env_var_name. When 'none', only method is present.
    105111 *
    106112 *             @type string $method          The authentication method: 'api_key' or 'none'.
    107113 *             @type string $credentials_url Optional. URL where users can obtain API credentials.
    108114 *             @type string $setting_name    Optional. The setting name for the API key.
     115 *             @type string $constant_name   Optional. PHP constant name for the API key.
     116 *             @type string $env_var_name    Optional. Environment variable name for the API key.
    109117 *         }
    110118 *         @type array       $plugin         {
     
    119127 *     description: non-empty-string,
    120128 *     logo_url?: non-empty-string,
    121  *     type: 'ai_provider',
     129 *     type: non-empty-string,
    122130 *     authentication: array{
    123131 *         method: 'api_key'|'none',
    124132 *         credentials_url?: non-empty-string,
    125  *         setting_name?: non-empty-string
     133 *         setting_name?: non-empty-string,
     134 *         constant_name?: non-empty-string,
     135 *         env_var_name?: non-empty-string
    126136 *     },
    127137 *     plugin?: array{
     
    217227     *
    218228     *     add_action( 'wp_connectors_init', function ( WP_Connector_Registry $registry ) {
    219      *         if ( $registry->is_registered( 'openai' ) ) {
    220      *             $connector = $registry->unregister( 'openai' );
    221      *             $connector['description'] = __( 'Custom description for OpenAI.', 'my-plugin' );
    222      *             $registry->register( 'openai', $connector );
     229     *         if ( $registry->is_registered( 'anthropic' ) ) {
     230     *             $connector = $registry->unregister( 'anthropic' );
     231     *             $connector['description'] = __( 'Custom description for Anthropic.', 'my-plugin' );
     232     *             $registry->register( 'anthropic', $connector );
    223233     *         }
    224234     *     } );
     
    336346    // Register all default connectors directly on the registry.
    337347    foreach ( $defaults as $id => $args ) {
     348        if ( 'api_key' === $args['authentication']['method'] ) {
     349            $sanitized_id = str_replace( '-', '_', $id );
     350
     351            if ( ! isset( $args['authentication']['setting_name'] ) ) {
     352                $args['authentication']['setting_name'] = "connectors_ai_{$sanitized_id}_api_key";
     353            }
     354
     355            // All AI providers use the {CONSTANT_CASE_ID}_API_KEY naming convention.
     356            if ( ! isset( $args['authentication']['constant_name'] ) || ! isset( $args['authentication']['env_var_name'] ) ) {
     357                $constant_case_key = strtoupper( preg_replace( '/([a-z])([A-Z])/', '$1_$2', $sanitized_id ) ) . '_API_KEY';
     358
     359                if ( ! isset( $args['authentication']['constant_name'] ) ) {
     360                    $args['authentication']['constant_name'] = $constant_case_key;
     361                }
     362
     363                if ( ! isset( $args['authentication']['env_var_name'] ) ) {
     364                    $args['authentication']['env_var_name'] = $constant_case_key;
     365                }
     366            }
     367        }
    338368        $registry->register( $id, $args );
    339369    }
     
    358388
    359389/**
    360  * Determines the source of an API key for a given provider.
     390 * Determines the source of an API key for a given connector.
    361391 *
    362392 * Checks in order: environment variable, PHP constant, database.
    363  * Uses the same naming convention as the WP AI Client ProviderRegistry.
    364  *
    365  * @since 7.0.0
    366  * @access private
    367  *
    368  * @param string $provider_id  The provider ID (e.g., 'openai', 'anthropic', 'google').
    369  * @param string $setting_name The option name for the API key (e.g., 'connectors_ai_openai_api_key').
     393 * Environment variable and constant are only checked when their
     394 * respective names are provided.
     395 *
     396 * @since 7.0.0
     397 * @access private
     398 *
     399 * @param string $setting_name  The option name for the API key (e.g., 'connectors_spam_filtering_akismet_api_key').
     400 * @param string $env_var_name  Optional. Environment variable name to check (e.g., 'AKISMET_API_KEY').
     401 * @param string $constant_name Optional. PHP constant name to check (e.g., 'AKISMET_API_KEY').
    370402 * @return string The key source: 'env', 'constant', 'database', or 'none'.
    371403 */
    372 function _wp_connectors_get_api_key_source( string $provider_id, string $setting_name ): string {
    373     // Convert provider ID to CONSTANT_CASE for env var name.
    374     // e.g., 'openai' -> 'OPENAI', 'anthropic' -> 'ANTHROPIC'.
    375     $constant_case_id = strtoupper(
    376         preg_replace( '/([a-z])([A-Z])/', '$1_$2', str_replace( '-', '_', $provider_id ) )
    377     );
    378     $env_var_name     = "{$constant_case_id}_API_KEY";
    379 
     404function _wp_connectors_get_api_key_source( string $setting_name, string $env_var_name = '', string $constant_name = '' ): string {
    380405    // Check environment variable first.
    381     $env_value = getenv( $env_var_name );
    382     if ( false !== $env_value && '' !== $env_value ) {
    383         return 'env';
     406    if ( '' !== $env_var_name ) {
     407        $env_value = getenv( $env_var_name );
     408        if ( false !== $env_value && '' !== $env_value ) {
     409            return 'env';
     410        }
    384411    }
    385412
    386413    // Check PHP constant.
    387     if ( defined( $env_var_name ) ) {
    388         $const_value = constant( $env_var_name );
     414    if ( '' !== $constant_name && defined( $constant_name ) ) {
     415        $const_value = constant( $constant_name );
    389416        if ( is_string( $const_value ) && '' !== $const_value ) {
    390417            return 'constant';
     
    471498    foreach ( wp_get_connectors() as $connector_id => $connector_data ) {
    472499        $auth = $connector_data['authentication'];
    473         if ( 'ai_provider' !== $connector_data['type'] || 'api_key' !== $auth['method'] || empty( $auth['setting_name'] ) ) {
     500        if ( 'api_key' !== $auth['method'] || empty( $auth['setting_name'] ) ) {
    474501            continue;
    475502        }
     
    482509        $value = $data[ $setting_name ];
    483510
    484         // On update, validate the key before masking.
    485         if ( $is_update && is_string( $value ) && '' !== $value ) {
     511        // On update, validate AI provider keys before masking.
     512        // Non-AI connectors accept keys as-is; the service plugin handles its own validation.
     513        if ( $is_update && is_string( $value ) && '' !== $value && 'ai_provider' === $connector_data['type'] ) {
    486514            if ( true !== _wp_connectors_is_ai_api_key_valid( $value, $connector_id ) ) {
    487515                update_option( $setting_name, '' );
     
    509537 */
    510538function _wp_register_default_connector_settings(): void {
    511     $ai_registry = AiClient::defaultRegistry();
     539    $ai_registry         = AiClient::defaultRegistry();
     540    $registered_settings = get_registered_settings();
    512541
    513542    foreach ( wp_get_connectors() as $connector_id => $connector_data ) {
    514543        $auth = $connector_data['authentication'];
    515         if ( 'ai_provider' !== $connector_data['type'] || 'api_key' !== $auth['method'] || empty( $auth['setting_name'] ) ) {
     544        if ( 'api_key' !== $auth['method'] || empty( $auth['setting_name'] ) ) {
    516545            continue;
    517546        }
    518547
    519         // Skip registering the setting if the provider is not in the registry.
    520         if ( ! $ai_registry->hasProvider( $connector_id ) ) {
     548        // Skip if the setting is already registered (e.g. by an owning plugin).
     549        if ( isset( $registered_settings[ $auth['setting_name'] ] ) ) {
     550            continue;
     551        }
     552
     553        // For AI providers, skip if the provider is not in the AI Client registry.
     554        if ( 'ai_provider' === $connector_data['type'] && ! $ai_registry->hasProvider( $connector_id ) ) {
    521555            continue;
    522556        }
     
    528562                'type'              => 'string',
    529563                'label'             => sprintf(
    530                     /* translators: %s: AI provider name. */
     564                    /* translators: %s: Connector name. */
    531565                    __( '%s API Key' ),
    532566                    $connector_data['name']
    533567                ),
    534568                'description'       => sprintf(
    535                     /* translators: %s: AI provider name. */
    536                     __( 'API key for the %s AI provider.' ),
     569                    /* translators: %s: Connector name. */
     570                    __( 'API key for the %s connector.' ),
    537571                    $connector_data['name']
    538572                ),
     
    570604
    571605            // Skip if the key is already provided via env var or constant.
    572             $key_source = _wp_connectors_get_api_key_source( $connector_id, $auth['setting_name'] );
     606            $key_source = _wp_connectors_get_api_key_source( $auth['setting_name'], $auth['env_var_name'] ?? '', $auth['constant_name'] ?? '' );
    573607            if ( 'env' === $key_source || 'constant' === $key_source ) {
    574608                continue;
     
    621655            $auth_out['settingName']    = $auth['setting_name'] ?? '';
    622656            $auth_out['credentialsUrl'] = $auth['credentials_url'] ?? null;
    623             $auth_out['keySource']      = _wp_connectors_get_api_key_source( $connector_id, $auth['setting_name'] ?? '' );
    624             try {
    625                 $auth_out['isConnected'] = $registry->hasProvider( $connector_id ) && $registry->isProviderConfigured( $connector_id );
    626             } catch ( Exception $e ) {
    627                 $auth_out['isConnected'] = false;
     657            $key_source                 = _wp_connectors_get_api_key_source( $auth['setting_name'] ?? '', $auth['env_var_name'] ?? '', $auth['constant_name'] ?? '' );
     658            $auth_out['keySource']      = $key_source;
     659
     660            if ( 'ai_provider' === $connector_data['type'] ) {
     661                try {
     662                    $auth_out['isConnected'] = $registry->hasProvider( $connector_id ) && $registry->isProviderConfigured( $connector_id );
     663                } catch ( Exception $e ) {
     664                    $auth_out['isConnected'] = false;
     665                }
     666            } else {
     667                $auth_out['isConnected'] = 'none' !== $key_source;
    628668            }
    629669        }
     
    646686            $connector_out['plugin'] = array(
    647687                'slug'        => $plugin_slug,
    648                 'isInstalled' => $is_installed,
     688                'pluginFile'  => $is_installed
     689                    ? ( str_ends_with( $plugin_file, '.php' ) ? substr( $plugin_file, 0, -4 ) : $plugin_file )
     690                    : null,
    649691                'isActivated' => $is_activated,
    650692            );
  • branches/7.0/tests/phpunit/includes/wp-ai-client-mock-provider-trait.php

    r62056 r62194  
    173173                        'method'          => 'api_key',
    174174                        'credentials_url' => null,
     175                        'setting_name'    => 'connectors_ai_mock_connectors_test_api_key',
    175176                    ),
    176177                )
  • branches/7.0/tests/phpunit/tests/connectors/wpConnectorRegistry.php

    r62067 r62194  
    3333
    3434        self::$default_args = array(
    35             'name'           => 'Test Provider',
    36             'description'    => 'A test AI provider.',
    37             'type'           => 'ai_provider',
     35            'name'           => 'Test Connector',
     36            'description'    => 'A test connector.',
     37            'type'           => 'test_type',
    3838            'authentication' => array(
    3939                'method'          => 'api_key',
     
    5050
    5151        $this->assertIsArray( $result );
    52         $this->assertSame( 'Test Provider', $result['name'] );
    53         $this->assertSame( 'A test AI provider.', $result['description'] );
    54         $this->assertSame( 'ai_provider', $result['type'] );
     52        $this->assertSame( 'Test Connector', $result['name'] );
     53        $this->assertSame( 'A test connector.', $result['description'] );
     54        $this->assertSame( 'test_type', $result['type'] );
    5555        $this->assertSame( 'api_key', $result['authentication']['method'] );
    5656        $this->assertSame( 'https://example.com/keys', $result['authentication']['credentials_url'] );
    57         $this->assertSame( 'connectors_ai_test_provider_api_key', $result['authentication']['setting_name'] );
     57        $this->assertSame( 'connectors_test_type_test_provider_api_key', $result['authentication']['setting_name'] );
    5858    }
    5959
     
    6464        $result = $this->registry->register( 'myai', self::$default_args );
    6565
    66         $this->assertSame( 'connectors_ai_myai_api_key', $result['authentication']['setting_name'] );
     66        $this->assertSame( 'connectors_test_type_myai_api_key', $result['authentication']['setting_name'] );
    6767    }
    6868
     
    7373        $result = $this->registry->register( 'my-ai', self::$default_args );
    7474
    75         $this->assertSame( 'connectors_ai_my_ai_api_key', $result['authentication']['setting_name'] );
     75        $this->assertSame( 'connectors_test_type_my_ai_api_key', $result['authentication']['setting_name'] );
     76    }
     77
     78    /**
     79     * @ticket 64957
     80     */
     81    public function test_register_generates_setting_name_using_type_and_id() {
     82        $args         = self::$default_args;
     83        $args['type'] = 'email_delivery';
     84
     85        $result = $this->registry->register( 'sendgrid', $args );
     86
     87        $this->assertSame( 'connectors_email_delivery_sendgrid_api_key', $result['authentication']['setting_name'] );
     88    }
     89
     90    /**
     91     * @ticket 64957
     92     */
     93    public function test_register_uses_custom_setting_name_when_provided() {
     94        $args                                   = self::$default_args;
     95        $args['authentication']['setting_name'] = 'wordpress_api_key';
     96
     97        $result = $this->registry->register( 'custom-setting', $args );
     98
     99        $this->assertSame( 'wordpress_api_key', $result['authentication']['setting_name'] );
     100    }
     101
     102    /**
     103     * @ticket 64957
     104     */
     105    public function test_register_rejects_empty_setting_name() {
     106        $this->setExpectedIncorrectUsage( 'WP_Connector_Registry::register' );
     107
     108        $args                                   = self::$default_args;
     109        $args['authentication']['setting_name'] = '';
     110
     111        $result = $this->registry->register( 'empty-setting', $args );
     112
     113        $this->assertNull( $result );
     114    }
     115
     116    /**
     117     * @ticket 64957
     118     */
     119    public function test_register_rejects_non_string_setting_name() {
     120        $this->setExpectedIncorrectUsage( 'WP_Connector_Registry::register' );
     121
     122        $args                                   = self::$default_args;
     123        $args['authentication']['setting_name'] = 123;
     124
     125        $result = $this->registry->register( 'non-string-setting', $args );
     126
     127        $this->assertNull( $result );
     128    }
     129
     130    /**
     131     * @ticket 64957
     132     */
     133    public function test_register_stores_constant_name_when_provided() {
     134        $args                                    = self::$default_args;
     135        $args['authentication']['constant_name'] = 'MY_PROVIDER_API_KEY';
     136
     137        $result = $this->registry->register( 'my-provider', $args );
     138
     139        $this->assertSame( 'MY_PROVIDER_API_KEY', $result['authentication']['constant_name'] );
     140    }
     141
     142    /**
     143     * @ticket 64957
     144     */
     145    public function test_register_omits_constant_name_when_not_provided() {
     146        $result = $this->registry->register( 'no-const', self::$default_args );
     147
     148        $this->assertArrayNotHasKey( 'constant_name', $result['authentication'] );
     149    }
     150
     151    /**
     152     * @ticket 64957
     153     */
     154    public function test_register_rejects_empty_constant_name() {
     155        $this->setExpectedIncorrectUsage( 'WP_Connector_Registry::register' );
     156
     157        $args                                    = self::$default_args;
     158        $args['authentication']['constant_name'] = '';
     159
     160        $result = $this->registry->register( 'empty-const', $args );
     161
     162        $this->assertNull( $result );
     163    }
     164
     165    /**
     166     * @ticket 64957
     167     */
     168    public function test_register_rejects_non_string_constant_name() {
     169        $this->setExpectedIncorrectUsage( 'WP_Connector_Registry::register' );
     170
     171        $args                                    = self::$default_args;
     172        $args['authentication']['constant_name'] = 123;
     173
     174        $result = $this->registry->register( 'bad-const', $args );
     175
     176        $this->assertNull( $result );
     177    }
     178
     179    /**
     180     * @ticket 64957
     181     */
     182    public function test_register_stores_env_var_name_when_provided() {
     183        $args                                   = self::$default_args;
     184        $args['authentication']['env_var_name'] = 'MY_PROVIDER_API_KEY';
     185
     186        $result = $this->registry->register( 'my-provider', $args );
     187
     188        $this->assertSame( 'MY_PROVIDER_API_KEY', $result['authentication']['env_var_name'] );
     189    }
     190
     191    /**
     192     * @ticket 64957
     193     */
     194    public function test_register_omits_env_var_name_when_not_provided() {
     195        $result = $this->registry->register( 'no-env', self::$default_args );
     196
     197        $this->assertArrayNotHasKey( 'env_var_name', $result['authentication'] );
     198    }
     199
     200    /**
     201     * @ticket 64957
     202     */
     203    public function test_register_rejects_empty_env_var_name() {
     204        $this->setExpectedIncorrectUsage( 'WP_Connector_Registry::register' );
     205
     206        $args                                   = self::$default_args;
     207        $args['authentication']['env_var_name'] = '';
     208
     209        $result = $this->registry->register( 'empty-env', $args );
     210
     211        $this->assertNull( $result );
     212    }
     213
     214    /**
     215     * @ticket 64957
     216     */
     217    public function test_register_rejects_non_string_env_var_name() {
     218        $this->setExpectedIncorrectUsage( 'WP_Connector_Registry::register' );
     219
     220        $args                                   = self::$default_args;
     221        $args['authentication']['env_var_name'] = 123;
     222
     223        $result = $this->registry->register( 'bad-env', $args );
     224
     225        $this->assertNull( $result );
    76226    }
    77227
     
    81231    public function test_register_no_setting_name_for_none_auth() {
    82232        $args   = array(
    83             'name'           => 'No Auth Provider',
    84             'type'           => 'ai_provider',
     233            'name'           => 'No Auth Connector',
     234            'type'           => 'test_type',
    85235            'authentication' => array( 'method' => 'none' ),
    86236        );
     
    97247        $args = array(
    98248            'name'           => 'Minimal',
    99             'type'           => 'ai_provider',
     249            'type'           => 'test_type',
    100250            'authentication' => array( 'method' => 'none' ),
    101251        );
     
    309459
    310460        $this->assertIsArray( $result );
    311         $this->assertSame( 'Test Provider', $result['name'] );
     461        $this->assertSame( 'Test Connector', $result['name'] );
    312462    }
    313463
     
    356506
    357507        $this->assertIsArray( $result );
    358         $this->assertSame( 'Test Provider', $result['name'] );
     508        $this->assertSame( 'Test Connector', $result['name'] );
    359509        $this->assertFalse( $this->registry->is_registered( 'to-remove' ) );
    360510    }
     
    405555        add_filter( 'wp_supports_ai', '__return_false' );
    406556
    407         $this->registry->register( 'first', self::$default_args );
     557        $args         = self::$default_args;
     558        $args['type'] = 'ai_provider';
     559        $this->registry->register( 'first', $args );
    408560
    409561        $all = $this->registry->get_all_registered();
Note: See TracChangeset for help on using the changeset viewer.