407 lines
15 KiB
PHP
407 lines
15 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Beheert alle plugininstellingen: ophalen, standaardiseren en sanitizen.
|
|
*/
|
|
class Groq_AI_Settings_Manager {
|
|
/** @var string */
|
|
private $option_key;
|
|
|
|
/** @var Groq_AI_Provider_Manager */
|
|
private $provider_manager;
|
|
|
|
/** @var array|null */
|
|
private $context_field_definitions = null;
|
|
|
|
/** @var array|null */
|
|
private $default_modules = null;
|
|
|
|
public function __construct( $option_key, Groq_AI_Provider_Manager $provider_manager ) {
|
|
$this->option_key = $option_key;
|
|
$this->provider_manager = $provider_manager;
|
|
}
|
|
|
|
/**
|
|
* Geeft samengestelde instellingen terug (voormalige get_settings()).
|
|
*
|
|
* @return array
|
|
*/
|
|
public function all() {
|
|
$defaults = [
|
|
'provider' => 'groq',
|
|
'model' => '',
|
|
'store_context' => '',
|
|
'default_prompt' => '',
|
|
'max_output_tokens' => 2048,
|
|
'groq_api_key' => '',
|
|
'openai_api_key' => '',
|
|
'google_api_key' => '',
|
|
'google_oauth_client_id' => '',
|
|
'google_oauth_client_secret' => '',
|
|
'google_oauth_refresh_token' => '',
|
|
'google_oauth_connected_email' => '',
|
|
'google_oauth_connected_at' => 0,
|
|
'google_enable_gsc' => true,
|
|
'google_enable_ga' => true,
|
|
'google_gsc_site_url' => '',
|
|
'google_ga4_property_id' => '',
|
|
'context_fields' => $this->get_default_context_fields(),
|
|
'modules' => $this->get_default_modules_settings(),
|
|
'image_context_mode' => 'url',
|
|
'image_context_limit' => 3,
|
|
'response_format_compat' => false,
|
|
];
|
|
|
|
$settings = get_option( $this->option_key, [] );
|
|
$settings = wp_parse_args( (array) $settings, $defaults );
|
|
$settings['context_fields'] = $this->normalize_context_fields( isset( $settings['context_fields'] ) ? $settings['context_fields'] : [] );
|
|
$settings['modules'] = $this->sanitize_modules_settings( isset( $settings['modules'] ) ? $settings['modules'] : [] );
|
|
$settings['model'] = Groq_AI_Model_Exclusions::ensure_allowed( $settings['provider'], isset( $settings['model'] ) ? $settings['model'] : '' );
|
|
|
|
$image_mode = isset( $settings['image_context_mode'] ) ? sanitize_text_field( $settings['image_context_mode'] ) : 'url';
|
|
if ( 'none' === $image_mode ) {
|
|
$settings['context_fields']['images'] = false;
|
|
$settings['image_context_mode'] = 'none';
|
|
} elseif ( in_array( $image_mode, [ 'url', 'base64' ], true ) ) {
|
|
$settings['context_fields']['images'] = true;
|
|
$settings['image_context_mode'] = $image_mode;
|
|
} else {
|
|
$settings['context_fields']['images'] = true;
|
|
$settings['image_context_mode'] = 'url';
|
|
}
|
|
|
|
$limit = isset( $settings['image_context_limit'] ) ? $this->sanitize_image_context_limit_value( $settings['image_context_limit'] ) : 3;
|
|
$settings['image_context_limit'] = $limit;
|
|
|
|
return $settings;
|
|
}
|
|
|
|
/**
|
|
* Sanitizelogica voor register_setting callback.
|
|
*
|
|
* @param array $input
|
|
* @return array
|
|
*/
|
|
public function sanitize( $input ) {
|
|
$base_defaults = [
|
|
'provider' => 'groq',
|
|
'model' => '',
|
|
'store_context' => '',
|
|
'default_prompt' => '',
|
|
'max_output_tokens' => 2048,
|
|
'groq_api_key' => '',
|
|
'openai_api_key' => '',
|
|
'google_api_key' => '',
|
|
'google_oauth_client_id' => '',
|
|
'google_oauth_client_secret' => '',
|
|
'google_oauth_refresh_token' => '',
|
|
'google_oauth_connected_email' => '',
|
|
'google_oauth_connected_at' => 0,
|
|
'google_enable_gsc' => true,
|
|
'google_enable_ga' => true,
|
|
'google_gsc_site_url' => '',
|
|
'google_ga4_property_id' => '',
|
|
'context_fields' => $this->get_default_context_fields(),
|
|
'modules' => $this->get_default_modules_settings(),
|
|
'image_context_mode' => 'url',
|
|
'image_context_limit' => 3,
|
|
'response_format_compat' => false,
|
|
];
|
|
|
|
$current_settings = $this->all();
|
|
$defaults = wp_parse_args( $current_settings, $base_defaults );
|
|
$raw_input = (array) $input;
|
|
$input = wp_parse_args( $raw_input, $defaults );
|
|
$context_posted = array_key_exists( 'context_fields', $raw_input );
|
|
$modules_posted = array_key_exists( 'modules', $raw_input );
|
|
|
|
$provider = sanitize_text_field( $input['provider'] );
|
|
if ( ! $this->provider_manager->get_provider( $provider ) ) {
|
|
$provider = 'groq';
|
|
}
|
|
|
|
$model = sanitize_text_field( $input['model'] );
|
|
$model = Groq_AI_Model_Exclusions::ensure_allowed( $provider, $model );
|
|
|
|
$image_mode = isset( $input['image_context_mode'] ) ? sanitize_text_field( $input['image_context_mode'] ) : $defaults['image_context_mode'];
|
|
$allowed_modes = [ 'none', 'base64', 'url' ];
|
|
if ( ! in_array( $image_mode, $allowed_modes, true ) ) {
|
|
$image_mode = 'url';
|
|
}
|
|
|
|
$image_limit = isset( $input['image_context_limit'] ) ? $this->sanitize_image_context_limit_value( $input['image_context_limit'] ) : $defaults['image_context_limit'];
|
|
|
|
$max_output_tokens = isset( $input['max_output_tokens'] ) ? absint( $input['max_output_tokens'] ) : absint( $defaults['max_output_tokens'] );
|
|
// Keep within sane bounds across providers.
|
|
$max_output_tokens = max( 128, min( 8192, $max_output_tokens ) );
|
|
|
|
$context_fields = $this->normalize_context_fields( $context_posted ? $raw_input['context_fields'] : $defaults['context_fields'] );
|
|
|
|
if ( 'none' === $image_mode ) {
|
|
$context_fields['images'] = false;
|
|
} else {
|
|
$context_fields['images'] = true;
|
|
}
|
|
|
|
return [
|
|
'provider' => $provider,
|
|
'model' => $model,
|
|
'store_context' => sanitize_textarea_field( $input['store_context'] ),
|
|
'default_prompt' => sanitize_textarea_field( $input['default_prompt'] ),
|
|
'max_output_tokens' => $max_output_tokens,
|
|
'groq_api_key' => sanitize_text_field( $input['groq_api_key'] ),
|
|
'openai_api_key' => sanitize_text_field( $input['openai_api_key'] ),
|
|
'google_api_key' => sanitize_text_field( $input['google_api_key'] ),
|
|
'google_oauth_client_id' => sanitize_text_field( $input['google_oauth_client_id'] ),
|
|
'google_oauth_client_secret' => sanitize_text_field( $input['google_oauth_client_secret'] ),
|
|
'google_oauth_refresh_token' => sanitize_text_field( $input['google_oauth_refresh_token'] ),
|
|
'google_oauth_connected_email' => sanitize_text_field( $input['google_oauth_connected_email'] ),
|
|
'google_oauth_connected_at' => absint( $input['google_oauth_connected_at'] ),
|
|
'google_enable_gsc' => ! empty( $raw_input['google_enable_gsc'] ),
|
|
'google_enable_ga' => ! empty( $raw_input['google_enable_ga'] ),
|
|
'google_gsc_site_url' => esc_url_raw( (string) $input['google_gsc_site_url'] ),
|
|
'google_ga4_property_id' => sanitize_text_field( (string) $input['google_ga4_property_id'] ),
|
|
'response_format_compat' => ! empty( $raw_input['response_format_compat'] ),
|
|
'image_context_mode' => $image_mode,
|
|
'image_context_limit' => $image_limit,
|
|
'context_fields' => $context_fields,
|
|
'modules' => $this->sanitize_modules_settings(
|
|
$modules_posted ? $raw_input['modules'] : [],
|
|
$defaults['modules'],
|
|
isset( $current_settings['modules'] ) ? (array) $current_settings['modules'] : $this->get_default_modules_settings(),
|
|
$modules_posted
|
|
),
|
|
];
|
|
}
|
|
|
|
public function get_context_field_definitions() {
|
|
if ( null === $this->context_field_definitions ) {
|
|
$this->context_field_definitions = [
|
|
'title' => [
|
|
'label' => __( 'Producttitel', GROQ_AI_PRODUCT_TEXT_DOMAIN ),
|
|
'description' => __( 'Voeg de huidige producttitel toe als context.', GROQ_AI_PRODUCT_TEXT_DOMAIN ),
|
|
'default' => true,
|
|
],
|
|
'short_description' => [
|
|
'label' => __( 'Korte beschrijving', GROQ_AI_PRODUCT_TEXT_DOMAIN ),
|
|
'description' => __( 'Gebruik de bestaande korte beschrijving (indien aanwezig).', GROQ_AI_PRODUCT_TEXT_DOMAIN ),
|
|
'default' => true,
|
|
],
|
|
'description' => [
|
|
'label' => __( 'Volledige beschrijving', GROQ_AI_PRODUCT_TEXT_DOMAIN ),
|
|
'description' => __( 'Stuurt de huidige productbeschrijving mee als bronmateriaal.', GROQ_AI_PRODUCT_TEXT_DOMAIN ),
|
|
'default' => true,
|
|
],
|
|
'attributes' => [
|
|
'label' => __( 'Attributen', GROQ_AI_PRODUCT_TEXT_DOMAIN ),
|
|
'description' => __( 'Voeg gestructureerde productattributen toe (zoals kleur, maat, materiaal).', GROQ_AI_PRODUCT_TEXT_DOMAIN ),
|
|
'default' => false,
|
|
],
|
|
'images' => [
|
|
'label' => __( 'Afbeeldingen', GROQ_AI_PRODUCT_TEXT_DOMAIN ),
|
|
'description' => __( 'Voeg een korte lijst toe met productafbeeldingen (beschrijving + URL).', GROQ_AI_PRODUCT_TEXT_DOMAIN ),
|
|
'default' => false,
|
|
],
|
|
];
|
|
}
|
|
|
|
return $this->context_field_definitions;
|
|
}
|
|
|
|
public function get_default_context_fields() {
|
|
$definitions = $this->get_context_field_definitions();
|
|
$defaults = [];
|
|
|
|
foreach ( $definitions as $key => $data ) {
|
|
$defaults[ $key ] = ! empty( $data['default'] );
|
|
}
|
|
|
|
return $defaults;
|
|
}
|
|
|
|
public function normalize_context_fields( $fields ) {
|
|
$definitions = $this->get_context_field_definitions();
|
|
$normalized = [];
|
|
|
|
foreach ( $definitions as $key => $data ) {
|
|
$normalized[ $key ] = false;
|
|
}
|
|
|
|
if ( ! is_array( $fields ) ) {
|
|
return $normalized;
|
|
}
|
|
|
|
foreach ( $fields as $key => $value ) {
|
|
if ( is_int( $key ) ) {
|
|
$key = sanitize_text_field( $value );
|
|
$value = true;
|
|
}
|
|
|
|
if ( array_key_exists( $key, $normalized ) ) {
|
|
$normalized[ $key ] = (bool) $value;
|
|
}
|
|
}
|
|
|
|
return $normalized;
|
|
}
|
|
|
|
public function get_default_modules_settings() {
|
|
if ( null === $this->default_modules ) {
|
|
$this->default_modules = [
|
|
'rankmath' => [
|
|
'enabled' => true,
|
|
'focus_keyword_limit' => 3,
|
|
'meta_title_pixel_limit' => 580,
|
|
'meta_description_pixel_limit' => 920,
|
|
],
|
|
];
|
|
}
|
|
|
|
return $this->default_modules;
|
|
}
|
|
|
|
public function get_module_config( $module, $settings = null ) {
|
|
if ( null === $settings ) {
|
|
$settings = $this->all();
|
|
}
|
|
|
|
$defaults = $this->get_default_modules_settings();
|
|
$modules = isset( $settings['modules'] ) && is_array( $settings['modules'] ) ? $settings['modules'] : [];
|
|
$config = isset( $modules[ $module ] ) ? (array) $modules[ $module ] : [];
|
|
|
|
return wp_parse_args( $config, isset( $defaults[ $module ] ) ? $defaults[ $module ] : [] );
|
|
}
|
|
|
|
public function is_module_enabled( $module, $settings = null ) {
|
|
$config = $this->get_module_config( $module, $settings );
|
|
|
|
return ! empty( $config['enabled'] );
|
|
}
|
|
|
|
public function get_rankmath_focus_keyword_limit( $settings = null ) {
|
|
$config = $this->get_module_config( 'rankmath', $settings );
|
|
$limit = isset( $config['focus_keyword_limit'] ) ? absint( $config['focus_keyword_limit'] ) : 3;
|
|
|
|
return max( 1, min( 10, $limit ) );
|
|
}
|
|
|
|
public function get_rankmath_meta_title_pixel_limit( $settings = null ) {
|
|
$config = $this->get_module_config( 'rankmath', $settings );
|
|
$value = isset( $config['meta_title_pixel_limit'] ) ? absint( $config['meta_title_pixel_limit'] ) : 580;
|
|
|
|
return max( 200, min( 1200, $value ) );
|
|
}
|
|
|
|
public function get_rankmath_meta_description_pixel_limit( $settings = null ) {
|
|
$config = $this->get_module_config( 'rankmath', $settings );
|
|
$value = isset( $config['meta_description_pixel_limit'] ) ? absint( $config['meta_description_pixel_limit'] ) : 920;
|
|
|
|
return max( 200, min( 2000, $value ) );
|
|
}
|
|
|
|
public function get_image_context_mode( $settings = null ) {
|
|
if ( null === $settings ) {
|
|
$settings = $this->all();
|
|
}
|
|
|
|
$mode = isset( $settings['image_context_mode'] ) ? sanitize_text_field( $settings['image_context_mode'] ) : 'url';
|
|
$allowed_modes = [ 'none', 'base64', 'url' ];
|
|
|
|
return in_array( $mode, $allowed_modes, true ) ? $mode : 'url';
|
|
}
|
|
|
|
public function get_image_context_limit( $settings = null ) {
|
|
if ( null === $settings ) {
|
|
$settings = $this->all();
|
|
}
|
|
|
|
$limit = isset( $settings['image_context_limit'] ) ? $settings['image_context_limit'] : 3;
|
|
|
|
return $this->sanitize_image_context_limit_value( $limit );
|
|
}
|
|
|
|
public function is_response_format_compat_enabled( $settings = null ) {
|
|
if ( null === $settings ) {
|
|
$settings = $this->all();
|
|
}
|
|
|
|
return ! empty( $settings['response_format_compat'] );
|
|
}
|
|
|
|
/**
|
|
* @param array|null $modules
|
|
* @param array|null $defaults
|
|
* @param array|null $current
|
|
* @param bool $is_posted
|
|
* @return array
|
|
*/
|
|
private function sanitize_modules_settings( $modules, $defaults = null, $current = null, $is_posted = false ) {
|
|
$module_defaults = $this->get_default_modules_settings();
|
|
|
|
if ( ! is_array( $defaults ) ) {
|
|
$defaults = $module_defaults;
|
|
}
|
|
|
|
if ( ! is_array( $current ) ) {
|
|
$current = $defaults;
|
|
}
|
|
|
|
$current = wp_parse_args( $current, $defaults );
|
|
|
|
if ( ! is_array( $modules ) ) {
|
|
$modules = [];
|
|
}
|
|
|
|
if ( ! $is_posted ) {
|
|
$clean = [];
|
|
foreach ( $module_defaults as $module_key => $module_default_config ) {
|
|
$raw = isset( $modules[ $module_key ] ) ? (array) $modules[ $module_key ] : [];
|
|
$clean[ $module_key ] = wp_parse_args( $raw, isset( $current[ $module_key ] ) ? $current[ $module_key ] : $module_default_config );
|
|
}
|
|
|
|
return $clean;
|
|
}
|
|
|
|
$result = $current;
|
|
|
|
foreach ( $module_defaults as $module_key => $module_default_config ) {
|
|
$raw = isset( $modules[ $module_key ] ) ? (array) $modules[ $module_key ] : [];
|
|
$current_config = isset( $current[ $module_key ] ) ? (array) $current[ $module_key ] : $module_default_config;
|
|
|
|
$result[ $module_key ]['enabled'] = isset( $raw['enabled'] ) ? (bool) $raw['enabled'] : ( isset( $current_config['enabled'] ) ? (bool) $current_config['enabled'] : false );
|
|
|
|
if ( 'rankmath' === $module_key ) {
|
|
$limit = isset( $raw['focus_keyword_limit'] ) ? absint( $raw['focus_keyword_limit'] ) : ( isset( $current_config['focus_keyword_limit'] ) ? absint( $current_config['focus_keyword_limit'] ) : $module_default_config['focus_keyword_limit'] );
|
|
if ( $limit <= 0 ) {
|
|
$limit = $module_default_config['focus_keyword_limit'];
|
|
}
|
|
$result[ $module_key ]['focus_keyword_limit'] = max( 1, min( 10, $limit ) );
|
|
|
|
$title_pixel_limit = isset( $raw['meta_title_pixel_limit'] ) ? absint( $raw['meta_title_pixel_limit'] ) : ( isset( $current_config['meta_title_pixel_limit'] ) ? absint( $current_config['meta_title_pixel_limit'] ) : $module_default_config['meta_title_pixel_limit'] );
|
|
if ( $title_pixel_limit <= 0 ) {
|
|
$title_pixel_limit = $module_default_config['meta_title_pixel_limit'];
|
|
}
|
|
$result[ $module_key ]['meta_title_pixel_limit'] = max( 200, min( 1200, $title_pixel_limit ) );
|
|
|
|
$pixel_limit = isset( $raw['meta_description_pixel_limit'] ) ? absint( $raw['meta_description_pixel_limit'] ) : ( isset( $current_config['meta_description_pixel_limit'] ) ? absint( $current_config['meta_description_pixel_limit'] ) : $module_default_config['meta_description_pixel_limit'] );
|
|
if ( $pixel_limit <= 0 ) {
|
|
$pixel_limit = $module_default_config['meta_description_pixel_limit'];
|
|
}
|
|
$result[ $module_key ]['meta_description_pixel_limit'] = max( 200, min( 2000, $pixel_limit ) );
|
|
}
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
private function sanitize_image_context_limit_value( $value ) {
|
|
$limit = absint( $value );
|
|
|
|
if ( $limit <= 0 ) {
|
|
$limit = 1;
|
|
}
|
|
|
|
return min( 10, $limit );
|
|
}
|
|
}
|