181 lines
13 KiB
PHP
181 lines
13 KiB
PHP
<?php
|
|
|
|
namespace CropLogic;
|
|
|
|
if ( ! defined( 'ABSPATH' ) ) {
|
|
exit;
|
|
}
|
|
|
|
class Settings {
|
|
const OPTION_KEY = 'crop_logic_options';
|
|
|
|
/**
|
|
* @var Settings|null
|
|
*/
|
|
private static $instance = null;
|
|
|
|
public static function instance(): Settings {
|
|
if ( null === self::$instance ) {
|
|
self::$instance = new self();
|
|
}
|
|
|
|
return self::$instance;
|
|
}
|
|
|
|
private function __construct() {
|
|
add_action( 'admin_menu', [ $this, 'register_menu' ] );
|
|
add_action( 'admin_init', [ $this, 'register_settings' ] );
|
|
}
|
|
|
|
public static function defaults(): array {
|
|
return [
|
|
'provider' => 'custom_json',
|
|
'endpoint_url' => 'http://backend-web:8000',
|
|
'api_key' => '',
|
|
'model' => '',
|
|
'system_prompt' => '',
|
|
'temperature' => '0.7',
|
|
'timeout' => '25',
|
|
'custom_headers' => '',
|
|
'create_thread_path' => '/api/farm-ai-assistant/chats/',
|
|
'list_threads_path' => '/api/farm-ai-assistant/chats/',
|
|
'delete_thread_path' => '/api/farm-ai-assistant/chats/{conversation_id}/',
|
|
'get_messages_path' => '/api/farm-ai-assistant/chats/{conversation_id}/messages/',
|
|
'create_message_path' => '/api/farm-ai-assistant/chat/task/',
|
|
'task_status_path' => '/api/farm-ai-assistant/chat/task/{task_id}/status/',
|
|
'verify_path' => '/api/auth/verify/',
|
|
'login_path' => '/api/auth/login/',
|
|
'register_path' => '/api/auth/register/',
|
|
'forgot_path' => '/api/auth/forgot-password/',
|
|
'reset_path' => '/api/auth/reset-password/',
|
|
'token_header' => 'Authorization',
|
|
'token_prefix' => 'Bearer ',
|
|
];
|
|
}
|
|
|
|
public static function get_options(): array {
|
|
$options = get_option( self::OPTION_KEY, [] );
|
|
if ( ! is_array( $options ) ) {
|
|
$options = [];
|
|
}
|
|
return wp_parse_args( $options, self::defaults() );
|
|
}
|
|
|
|
public function register_menu(): void {
|
|
add_menu_page(
|
|
__( 'تنظیمات Crop Logic', 'crop-logic' ),
|
|
__( 'Crop Logic', 'crop-logic' ),
|
|
'manage_options',
|
|
'crop-logic',
|
|
[ $this, 'render_page' ],
|
|
'dashicons-format-chat',
|
|
56
|
|
);
|
|
}
|
|
|
|
public function register_settings(): void {
|
|
register_setting(
|
|
'crop_logic',
|
|
self::OPTION_KEY,
|
|
[
|
|
'type' => 'array',
|
|
'sanitize_callback' => [ $this, 'sanitize_options' ],
|
|
'default' => self::defaults(),
|
|
]
|
|
);
|
|
}
|
|
|
|
public function sanitize_options( $input ): array {
|
|
$defaults = self::defaults();
|
|
$input = is_array( $input ) ? $input : [];
|
|
$options = [];
|
|
|
|
$options['provider'] = in_array( $input['provider'] ?? '', [ 'custom_json', 'openai_compatible' ], true ) ? $input['provider'] : $defaults['provider'];
|
|
$options['endpoint_url'] = esc_url_raw( trim( (string) ( $input['endpoint_url'] ?? '' ) ) );
|
|
$options['api_key'] = sanitize_text_field( (string) ( $input['api_key'] ?? '' ) );
|
|
$options['model'] = sanitize_text_field( (string) ( $input['model'] ?? '' ) );
|
|
$options['system_prompt'] = sanitize_textarea_field( (string) ( $input['system_prompt'] ?? '' ) );
|
|
$options['custom_headers'] = trim( (string) ( $input['custom_headers'] ?? '' ) );
|
|
$options['create_thread_path'] = $this->sanitize_path_template( (string) ( $input['create_thread_path'] ?? $defaults['create_thread_path'] ) );
|
|
$options['list_threads_path'] = $this->sanitize_path_template( (string) ( $input['list_threads_path'] ?? $defaults['list_threads_path'] ) );
|
|
$options['delete_thread_path'] = $this->sanitize_path_template( (string) ( $input['delete_thread_path'] ?? $defaults['delete_thread_path'] ) );
|
|
$options['get_messages_path'] = $this->sanitize_path_template( (string) ( $input['get_messages_path'] ?? $defaults['get_messages_path'] ) );
|
|
$options['create_message_path'] = $this->sanitize_path_template( (string) ( $input['create_message_path'] ?? $defaults['create_message_path'] ) );
|
|
$options['task_status_path'] = $this->sanitize_path_template( (string) ( $input['task_status_path'] ?? $defaults['task_status_path'] ) );
|
|
$options['verify_path'] = $this->sanitize_path_template( (string) ( $input['verify_path'] ?? $defaults['verify_path'] ) );
|
|
$options['login_path'] = $this->sanitize_path_template( (string) ( $input['login_path'] ?? $defaults['login_path'] ) );
|
|
$options['register_path'] = $this->sanitize_path_template( (string) ( $input['register_path'] ?? $defaults['register_path'] ) );
|
|
$options['forgot_path'] = $this->sanitize_path_template( (string) ( $input['forgot_path'] ?? $defaults['forgot_path'] ) );
|
|
$options['reset_path'] = $this->sanitize_path_template( (string) ( $input['reset_path'] ?? $defaults['reset_path'] ) );
|
|
$options['token_header'] = sanitize_text_field( (string) ( $input['token_header'] ?? $defaults['token_header'] ) );
|
|
$options['token_prefix'] = (string) ( $input['token_prefix'] ?? $defaults['token_prefix'] );
|
|
|
|
$temperature = is_numeric( $input['temperature'] ?? null ) ? (float) $input['temperature'] : (float) $defaults['temperature'];
|
|
$timeout = is_numeric( $input['timeout'] ?? null ) ? (int) $input['timeout'] : (int) $defaults['timeout'];
|
|
$options['temperature'] = (string) max( 0, min( 2, $temperature ) );
|
|
$options['timeout'] = (string) max( 5, min( 120, $timeout ) );
|
|
|
|
if ( '' !== $options['custom_headers'] ) {
|
|
$json = json_decode( $options['custom_headers'], true );
|
|
if ( JSON_ERROR_NONE !== json_last_error() || ! is_array( $json ) ) {
|
|
$options['custom_headers'] = '';
|
|
add_settings_error( self::OPTION_KEY, 'crop_logic_headers', __( 'هدرهای سفارشی باید JSON معتبر باشند.', 'crop-logic' ) );
|
|
}
|
|
}
|
|
|
|
return wp_parse_args( $options, $defaults );
|
|
}
|
|
|
|
private function sanitize_path_template( string $path ): string {
|
|
$path = trim( $path );
|
|
if ( '' === $path ) {
|
|
return '/';
|
|
}
|
|
if ( '/' !== substr( $path, 0, 1 ) ) {
|
|
$path = '/' . $path;
|
|
}
|
|
return preg_replace( '#/+#', '/', $path ) ?: '/';
|
|
}
|
|
|
|
public function render_page(): void {
|
|
if ( ! current_user_can( 'manage_options' ) ) {
|
|
return;
|
|
}
|
|
|
|
$options = self::get_options();
|
|
?>
|
|
<div class="wrap">
|
|
<h1><?php echo esc_html__( 'تنظیمات API پلاگین Crop Logic', 'crop-logic' ); ?></h1>
|
|
<p><?php echo esc_html__( 'APIها بر اساس راهنمای Farm AI Assistant و Auth تنظیم شدهاند و وردپرس فقط نقش واسط را دارد.', 'crop-logic' ); ?></p>
|
|
<?php settings_errors( self::OPTION_KEY ); ?>
|
|
<form action="options.php" method="post">
|
|
<?php settings_fields( 'crop_logic' ); ?>
|
|
<table class="form-table" role="presentation">
|
|
<tr><th scope="row"><label for="crop_logic_endpoint_url"><?php echo esc_html__( 'آدرس پایه API', 'crop-logic' ); ?></label></th><td><input class="regular-text code" id="crop_logic_endpoint_url" name="<?php echo esc_attr( self::OPTION_KEY ); ?>[endpoint_url]" type="url" value="<?php echo esc_attr( $options['endpoint_url'] ); ?>" dir="ltr" /></td></tr>
|
|
<tr><th scope="row"><label for="crop_logic_api_key"><?php echo esc_html__( 'کلید API', 'crop-logic' ); ?></label></th><td><input class="regular-text" id="crop_logic_api_key" name="<?php echo esc_attr( self::OPTION_KEY ); ?>[api_key]" type="password" value="<?php echo esc_attr( $options['api_key'] ); ?>" autocomplete="off" dir="ltr" /></td></tr>
|
|
<tr><th scope="row"><label for="crop_logic_timeout"><?php echo esc_html__( 'مهلت پاسخ', 'crop-logic' ); ?></label></th><td><input class="small-text" id="crop_logic_timeout" name="<?php echo esc_attr( self::OPTION_KEY ); ?>[timeout]" type="number" min="5" max="120" step="1" value="<?php echo esc_attr( $options['timeout'] ); ?>" dir="ltr" /> <span><?php echo esc_html__( 'ثانیه', 'crop-logic' ); ?></span></td></tr>
|
|
<tr><th scope="row"><label for="crop_logic_custom_headers"><?php echo esc_html__( 'هدرهای سفارشی', 'crop-logic' ); ?></label></th><td><textarea class="large-text code" id="crop_logic_custom_headers" name="<?php echo esc_attr( self::OPTION_KEY ); ?>[custom_headers]" rows="4" dir="ltr"><?php echo esc_textarea( $options['custom_headers'] ); ?></textarea></td></tr>
|
|
<tr><th colspan="2"><h2><?php echo esc_html__( 'مسیرهای احراز هویت', 'crop-logic' ); ?></h2></th></tr>
|
|
<tr><th scope="row"><label for="crop_logic_verify_path"><?php echo esc_html__( 'verify', 'crop-logic' ); ?></label></th><td><input class="regular-text code" id="crop_logic_verify_path" name="<?php echo esc_attr( self::OPTION_KEY ); ?>[verify_path]" type="text" value="<?php echo esc_attr( $options['verify_path'] ); ?>" dir="ltr" /></td></tr>
|
|
<tr><th scope="row"><label for="crop_logic_login_path"><?php echo esc_html__( 'login', 'crop-logic' ); ?></label></th><td><input class="regular-text code" id="crop_logic_login_path" name="<?php echo esc_attr( self::OPTION_KEY ); ?>[login_path]" type="text" value="<?php echo esc_attr( $options['login_path'] ); ?>" dir="ltr" /></td></tr>
|
|
<tr><th scope="row"><label for="crop_logic_register_path"><?php echo esc_html__( 'register', 'crop-logic' ); ?></label></th><td><input class="regular-text code" id="crop_logic_register_path" name="<?php echo esc_attr( self::OPTION_KEY ); ?>[register_path]" type="text" value="<?php echo esc_attr( $options['register_path'] ); ?>" dir="ltr" /></td></tr>
|
|
<tr><th scope="row"><label for="crop_logic_forgot_path"><?php echo esc_html__( 'forgot password', 'crop-logic' ); ?></label></th><td><input class="regular-text code" id="crop_logic_forgot_path" name="<?php echo esc_attr( self::OPTION_KEY ); ?>[forgot_path]" type="text" value="<?php echo esc_attr( $options['forgot_path'] ); ?>" dir="ltr" /></td></tr>
|
|
<tr><th scope="row"><label for="crop_logic_reset_path"><?php echo esc_html__( 'reset password', 'crop-logic' ); ?></label></th><td><input class="regular-text code" id="crop_logic_reset_path" name="<?php echo esc_attr( self::OPTION_KEY ); ?>[reset_path]" type="text" value="<?php echo esc_attr( $options['reset_path'] ); ?>" dir="ltr" /></td></tr>
|
|
<tr><th colspan="2"><h2><?php echo esc_html__( 'مسیرهای چت', 'crop-logic' ); ?></h2></th></tr>
|
|
<tr><th scope="row"><label for="crop_logic_list_threads_path"><?php echo esc_html__( 'لیست گفتگوها', 'crop-logic' ); ?></label></th><td><input class="regular-text code" id="crop_logic_list_threads_path" name="<?php echo esc_attr( self::OPTION_KEY ); ?>[list_threads_path]" type="text" value="<?php echo esc_attr( $options['list_threads_path'] ); ?>" dir="ltr" /></td></tr>
|
|
<tr><th scope="row"><label for="crop_logic_create_thread_path"><?php echo esc_html__( 'ساخت گفتگوی خالی', 'crop-logic' ); ?></label></th><td><input class="regular-text code" id="crop_logic_create_thread_path" name="<?php echo esc_attr( self::OPTION_KEY ); ?>[create_thread_path]" type="text" value="<?php echo esc_attr( $options['create_thread_path'] ); ?>" dir="ltr" /></td></tr>
|
|
<tr><th scope="row"><label for="crop_logic_get_messages_path"><?php echo esc_html__( 'دریافت پیامها', 'crop-logic' ); ?></label></th><td><input class="regular-text code" id="crop_logic_get_messages_path" name="<?php echo esc_attr( self::OPTION_KEY ); ?>[get_messages_path]" type="text" value="<?php echo esc_attr( $options['get_messages_path'] ); ?>" dir="ltr" /></td></tr>
|
|
<tr><th scope="row"><label for="crop_logic_create_message_path"><?php echo esc_html__( 'ساخت task پیام', 'crop-logic' ); ?></label></th><td><input class="regular-text code" id="crop_logic_create_message_path" name="<?php echo esc_attr( self::OPTION_KEY ); ?>[create_message_path]" type="text" value="<?php echo esc_attr( $options['create_message_path'] ); ?>" dir="ltr" /></td></tr>
|
|
<tr><th scope="row"><label for="crop_logic_task_status_path"><?php echo esc_html__( 'وضعیت task', 'crop-logic' ); ?></label></th><td><input class="regular-text code" id="crop_logic_task_status_path" name="<?php echo esc_attr( self::OPTION_KEY ); ?>[task_status_path]" type="text" value="<?php echo esc_attr( $options['task_status_path'] ); ?>" dir="ltr" /></td></tr>
|
|
<tr><th scope="row"><label for="crop_logic_delete_thread_path"><?php echo esc_html__( 'حذف گفتگو', 'crop-logic' ); ?></label></th><td><input class="regular-text code" id="crop_logic_delete_thread_path" name="<?php echo esc_attr( self::OPTION_KEY ); ?>[delete_thread_path]" type="text" value="<?php echo esc_attr( $options['delete_thread_path'] ); ?>" dir="ltr" /></td></tr>
|
|
<tr><th colspan="2"><h2><?php echo esc_html__( 'توکن کاربر', 'crop-logic' ); ?></h2></th></tr>
|
|
<tr><th scope="row"><label for="crop_logic_token_header"><?php echo esc_html__( 'نام هدر توکن', 'crop-logic' ); ?></label></th><td><input class="regular-text code" id="crop_logic_token_header" name="<?php echo esc_attr( self::OPTION_KEY ); ?>[token_header]" type="text" value="<?php echo esc_attr( $options['token_header'] ); ?>" dir="ltr" /></td></tr>
|
|
<tr><th scope="row"><label for="crop_logic_token_prefix"><?php echo esc_html__( 'پیشوند توکن', 'crop-logic' ); ?></label></th><td><input class="regular-text code" id="crop_logic_token_prefix" name="<?php echo esc_attr( self::OPTION_KEY ); ?>[token_prefix]" type="text" value="<?php echo esc_attr( $options['token_prefix'] ); ?>" dir="ltr" /></td></tr>
|
|
</table>
|
|
<?php submit_button( __( 'ذخیره تنظیمات', 'crop-logic' ) ); ?>
|
|
</form>
|
|
</div>
|
|
<?php
|
|
}
|
|
}
|