From 667e9b1457b17a0d2dd2da37e54aa2ded8f72f87 Mon Sep 17 00:00:00 2001 From: Chris Huber Date: Sat, 17 Jan 2026 11:44:22 -0600 Subject: [PATCH 1/4] Add storage hooks for custom credential management - Add wp_ai_client_credentials filter to override credential retrieval - Add wp_ai_client_update_credentials action for custom storage - Closes #44 --- .../API_Credentials_Manager.php | 38 ++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/includes/API_Credentials/API_Credentials_Manager.php b/includes/API_Credentials/API_Credentials_Manager.php index b58a409..2f52671 100644 --- a/includes/API_Credentials/API_Credentials_Manager.php +++ b/includes/API_Credentials/API_Credentials_Manager.php @@ -209,6 +209,22 @@ private function register_settings(): void { } $credentials[ $provider_id ] = sanitize_text_field( $api_key ); } + /** + * Fires when AI provider credentials are updated. + * + * Allows implementers to store credentials in custom storage systems + * (e.g., encrypted tables, network options, external services). + * + * @since 0.2.0 + * + * @param array $credentials The sanitized credentials array. + * @param string $option_name The option name being updated. + */ + do_action( + 'wp_ai_client_update_credentials', + $credentials, + self::OPTION_PROVIDER_CREDENTIALS + ); return $credentials; }, ) @@ -225,7 +241,27 @@ private function register_settings(): void { * @throws RuntimeException If the stored credentials option is in an invalid format. */ private function pass_credentials_to_client(): void { - $credentials = get_option( self::OPTION_PROVIDER_CREDENTIALS, array() ); + /** + * Filters AI provider credentials storage. + * + * Returning a non-null value from this filter will bypass default + * get_option() behavior and use the returned value directly. + * + * @since 0.2.0 + * + * @param array|null $credentials The credentials array, or null to use default storage. + * @param string $option_name The option name being retrieved. + */ + $credentials = apply_filters( + 'wp_ai_client_credentials', + null, + self::OPTION_PROVIDER_CREDENTIALS + ); + + if ( $credentials === null ) { + $credentials = get_option( self::OPTION_PROVIDER_CREDENTIALS, array() ); + } + if ( ! is_array( $credentials ) ) { throw new RuntimeException( 'Invalid format for stored provider credentials option.' ); } From ee800c8cc9b4d914d02e6c7b946eb117c8e31e3f Mon Sep 17 00:00:00 2001 From: Chris Huber Date: Sat, 17 Jan 2026 12:20:01 -0600 Subject: [PATCH 2/4] Fix @since version to 0.2.1 --- includes/API_Credentials/API_Credentials_Manager.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/includes/API_Credentials/API_Credentials_Manager.php b/includes/API_Credentials/API_Credentials_Manager.php index 2f52671..0641b97 100644 --- a/includes/API_Credentials/API_Credentials_Manager.php +++ b/includes/API_Credentials/API_Credentials_Manager.php @@ -215,7 +215,7 @@ private function register_settings(): void { * Allows implementers to store credentials in custom storage systems * (e.g., encrypted tables, network options, external services). * - * @since 0.2.0 + * @since 0.2.1 * * @param array $credentials The sanitized credentials array. * @param string $option_name The option name being updated. @@ -247,7 +247,7 @@ private function pass_credentials_to_client(): void { * Returning a non-null value from this filter will bypass default * get_option() behavior and use the returned value directly. * - * @since 0.2.0 + * @since 0.2.1 * * @param array|null $credentials The credentials array, or null to use default storage. * @param string $option_name The option name being retrieved. From 2577eb1522a5353e016a747f8ae436bd82d0d350 Mon Sep 17 00:00:00 2001 From: Chris Huber Date: Sat, 17 Jan 2026 12:44:24 -0600 Subject: [PATCH 3/4] Change @since to placeholder n.e.x.t per contributing guidelines --- includes/API_Credentials/API_Credentials_Manager.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/includes/API_Credentials/API_Credentials_Manager.php b/includes/API_Credentials/API_Credentials_Manager.php index 0641b97..aefe209 100644 --- a/includes/API_Credentials/API_Credentials_Manager.php +++ b/includes/API_Credentials/API_Credentials_Manager.php @@ -215,7 +215,7 @@ private function register_settings(): void { * Allows implementers to store credentials in custom storage systems * (e.g., encrypted tables, network options, external services). * - * @since 0.2.1 + * @since n.e.x.t * * @param array $credentials The sanitized credentials array. * @param string $option_name The option name being updated. @@ -247,7 +247,7 @@ private function pass_credentials_to_client(): void { * Returning a non-null value from this filter will bypass default * get_option() behavior and use the returned value directly. * - * @since 0.2.1 + * @since n.e.x.t * * @param array|null $credentials The credentials array, or null to use default storage. * @param string $option_name The option name being retrieved. From ad6f0df0afe6a2271d2a2fe206710d82b21e509b Mon Sep 17 00:00:00 2001 From: Chris Huber Date: Sat, 17 Jan 2026 20:55:34 -0600 Subject: [PATCH 4/4] Fix PHPCS linting errors (trailing whitespace, Yoda condition) --- .../API_Credentials_Manager.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/includes/API_Credentials/API_Credentials_Manager.php b/includes/API_Credentials/API_Credentials_Manager.php index aefe209..e608466 100644 --- a/includes/API_Credentials/API_Credentials_Manager.php +++ b/includes/API_Credentials/API_Credentials_Manager.php @@ -220,10 +220,10 @@ private function register_settings(): void { * @param array $credentials The sanitized credentials array. * @param string $option_name The option name being updated. */ - do_action( - 'wp_ai_client_update_credentials', - $credentials, - self::OPTION_PROVIDER_CREDENTIALS + do_action( + 'wp_ai_client_update_credentials', + $credentials, + self::OPTION_PROVIDER_CREDENTIALS ); return $credentials; }, @@ -252,13 +252,13 @@ private function pass_credentials_to_client(): void { * @param array|null $credentials The credentials array, or null to use default storage. * @param string $option_name The option name being retrieved. */ - $credentials = apply_filters( - 'wp_ai_client_credentials', - null, - self::OPTION_PROVIDER_CREDENTIALS + $credentials = apply_filters( + 'wp_ai_client_credentials', + null, + self::OPTION_PROVIDER_CREDENTIALS ); - if ( $credentials === null ) { + if ( null === $credentials ) { $credentials = get_option( self::OPTION_PROVIDER_CREDENTIALS, array() ); }