-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Adds AI Settings Screen #10904
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adds AI Settings Screen #10904
Changes from all commits
1479dc5
2c842f1
99efae9
1c07c3e
23f1af0
42197b5
8a9d2c6
56c6873
a5bd792
242f9f9
7caa159
0edbfef
ebbdc54
278f753
85b1916
c494c59
0e78c62
1e2d52c
9626b32
62b33aa
52d4963
472f69f
b4f9bd7
9c3b25e
d708bd2
97f8598
9e0ebcc
76bc7ba
9364aca
87c0400
d97a86a
582d0d0
9098a6e
5f3c5be
00ef1b8
0e8a5dc
e8a2a2f
0774f6f
c58351d
7f94810
76af7a8
b5baa00
6fa12cb
a2852ac
18eba37
27cf7cf
1bf9bc6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,102 @@ | ||
| <?php | ||
| /** | ||
| * AI Services settings administration panel. | ||
| * | ||
| * @package WordPress | ||
| * @subpackage Administration | ||
| * @since 7.0.0 | ||
| */ | ||
|
|
||
| /** WordPress Administration Bootstrap */ | ||
| require_once __DIR__ . '/admin.php'; | ||
|
|
||
| if ( ! current_user_can( 'manage_options' ) ) { | ||
| wp_die( __( 'Sorry, you are not allowed to manage options for this site.' ) ); | ||
| } | ||
|
|
||
| // Used in the HTML title tag. | ||
| $title = __( 'AI Services Settings' ); | ||
| $parent_file = 'options-general.php'; | ||
|
|
||
| $credentials_manager = $GLOBALS['wp_ai_client_credentials_manager']; | ||
|
|
||
| $cloud_providers = $credentials_manager->get_all_cloud_providers_metadata(); | ||
|
|
||
| $settings_section = 'wp-ai-client-provider-credentials'; | ||
|
|
||
| add_settings_section( | ||
| $settings_section, | ||
| '', | ||
| static function () { | ||
| ?> | ||
| <p class="description"> | ||
| <?php _e( 'Paste your API credentials for one or more AI providers you would like to use throughout your site.' ); ?> | ||
| </p> | ||
| <?php | ||
| }, | ||
| 'ai' | ||
| ); | ||
|
|
||
| foreach ( $cloud_providers as $provider_metadata ) { | ||
| $provider_id = $provider_metadata->getId(); | ||
| $provider_name = $provider_metadata->getName(); | ||
| $provider_credentials_url = $provider_metadata->getCredentialsUrl(); | ||
|
|
||
| $field_id = 'wp-ai-client-provider-api-key-' . $provider_id; | ||
| $field_args = array( | ||
| 'type' => 'password', | ||
| 'label_for' => $field_id, | ||
| 'id' => $field_id, | ||
| 'name' => WP_AI_Client_Credentials_Manager::OPTION_PROVIDER_CREDENTIALS . '[' . $provider_id . ']', | ||
| ); | ||
| if ( $provider_credentials_url ) { | ||
| $field_args['description'] = sprintf( | ||
| /* translators: 1: AI provider name, 2: URL to the provider's API credentials page. */ | ||
| __( 'Create and manage your %1$s API keys in the <a href="%2$s" target="_blank" rel="noopener noreferrer">%1$s account settings<span class="screen-reader-text"> (opens in a new tab)</span></a>.' ), | ||
| $provider_name, | ||
| esc_url( $provider_credentials_url ) | ||
| ); | ||
| } | ||
|
|
||
| add_settings_field( | ||
| $field_id, | ||
| $provider_name, | ||
| 'wp_ai_client_render_credential_field', | ||
| 'ai', | ||
| $settings_section, | ||
| $field_args | ||
| ); | ||
| } | ||
|
|
||
| $ai_help = '<p>' . __( 'This screen allows you to configure API credentials for AI service providers. These credentials are used by AI-powered features throughout your site.' ) . '</p>'; | ||
| $ai_help .= '<p>' . __( 'You must click the Save Changes button at the bottom of the screen for new settings to take effect.' ) . '</p>'; | ||
|
|
||
| get_current_screen()->add_help_tab( | ||
| array( | ||
| 'id' => 'overview', | ||
| 'title' => __( 'Overview' ), | ||
| 'content' => $ai_help, | ||
| ) | ||
| ); | ||
|
|
||
| get_current_screen()->set_help_sidebar( | ||
| '<p><strong>' . __( 'For more information:' ) . '</strong></p>' . | ||
| '<p>' . __( '<a href="https://wordpress.org/support/forums/">Support forums</a>' ) . '</p>' | ||
| ); | ||
|
|
||
| require_once ABSPATH . 'wp-admin/admin-header.php'; | ||
|
|
||
| ?> | ||
|
|
||
| <div class="wrap"> | ||
| <h1><?php echo esc_html( $title ); ?></h1> | ||
|
|
||
| <form action="options.php" method="post"> | ||
| <?php settings_fields( 'ai' ); ?> | ||
| <?php do_settings_sections( 'ai' ); ?> | ||
| <?php submit_button(); ?> | ||
| </form> | ||
|
|
||
| </div> | ||
|
|
||
| <?php require_once ABSPATH . 'wp-admin/admin-footer.php'; ?> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -32,3 +32,72 @@ | |
| function wp_ai_client_prompt( $prompt = null ) { | ||
| return new WP_AI_Client_Prompt_Builder( AiClient::defaultRegistry(), $prompt ); | ||
| } | ||
|
|
||
| /** | ||
| * Renders a credential input field for the AI Services settings page. | ||
| * | ||
| * @since 7.0.0 | ||
| * @access private | ||
| * | ||
| * @param array $args { | ||
| * Field arguments set up during add_settings_field(). | ||
| * | ||
| * @type string $type Input type. Default 'text'. | ||
| * @type string $id Field ID attribute. | ||
| * @type string $name Field name attribute, may include array notation. | ||
| * @type string $description Optional. Field description HTML. | ||
| * } | ||
| */ | ||
| function wp_ai_client_render_credential_field( $args ) { | ||
| $type = isset( $args['type'] ) ? $args['type'] : 'text'; | ||
| $id = isset( $args['id'] ) ? $args['id'] : ''; | ||
| $name = isset( $args['name'] ) ? $args['name'] : ''; | ||
| $description = isset( $args['description'] ) ? $args['description'] : ''; | ||
| $description_id = $id . '_description'; | ||
|
|
||
| if ( str_contains( $name, '[' ) ) { | ||
| $parts = explode( '[', $name, 2 ); | ||
| $option = get_option( $parts[0] ); | ||
| $subkey = trim( $parts[1], ']' ); | ||
| if ( is_array( $option ) && isset( $option[ $subkey ] ) && is_string( $option[ $subkey ] ) ) { | ||
| $value = $option[ $subkey ]; | ||
| } else { | ||
| $value = ''; | ||
| } | ||
| } else { | ||
| $option = get_option( $name ); | ||
| $value = is_string( $option ) ? $option : ''; | ||
| } | ||
|
|
||
| ?> | ||
| <input | ||
| type="<?php echo esc_attr( $type ); ?>" | ||
| id="<?php echo esc_attr( $id ); ?>" | ||
| name="<?php echo esc_attr( $name ); ?>" | ||
| value="<?php echo esc_attr( $value ); ?>" | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Something we just fixed in ClassifAI that came in from a security review was to ensure credentials (like API keys) were obfuscated prior to rendering in our settings screens. While I know this will render as a password input, you can still easily inspect the source and get the value of the input. I also realize only those with the I do think this is an edge case so not saying it needs to be changed, just fresh on my mind as I just adjusted this behavior myself a few days ago :) |
||
| class="regular-text" | ||
| <?php echo $description ? 'aria-describedby="' . esc_attr( $description_id ) . '"' : ''; ?> | ||
| > | ||
| <?php | ||
|
|
||
| if ( $description ) { | ||
| $allowed_html = array( | ||
| 'a' => array( | ||
| 'class' => array(), | ||
| 'href' => array(), | ||
| 'target' => array(), | ||
| 'rel' => array(), | ||
| ), | ||
| 'strong' => array(), | ||
| 'em' => array(), | ||
| 'span' => array( | ||
| 'class' => array(), | ||
| ), | ||
| ); | ||
| ?> | ||
| <p id="<?php echo esc_attr( $description_id ); ?>" class="description"> | ||
| <?php echo wp_kses( $description, $allowed_html ); ?> | ||
| </p> | ||
| <?php | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a chance both
$idand$nameare empty. Might be better to not render these attributes in that case instead of rendering them as empty attributes