wpmind/includes/Routing/IntelligentRouter.php
LinuxJoy adb6c49301 style: phpcbf 自动格式化 — 全量 WPCS 3.x 规范对齐
135 文件 19,211 处自动修复:空格→Tab 缩进、括号间距、
函数声明空格、前置自增、尾逗号等纯格式化改动。
零逻辑变更,php -l + token 级对比验证通过。

新增 phpcs.xml.dist / phpstan.neon.dist 项目配置。

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 00:48:46 +08:00

344 lines
9.1 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* Intelligent Router - 智能路由器
*
* 基于策略的 Provider 路由选择
*
* @package WPMind
* @since 1.9.0
*/
declare(strict_types=1);
namespace WPMind\Routing;
use WPMind\Routing\Strategies\AvailabilityStrategy;
use WPMind\Routing\Strategies\CompositeStrategy;
use WPMind\Routing\Strategies\CostStrategy;
use WPMind\Routing\Strategies\LatencyStrategy;
use WPMind\Routing\Strategies\LoadBalancedStrategy;
class IntelligentRouter {
private static ?IntelligentRouter $instance = null;
/** @var array<string, RoutingStrategyInterface> 已注册的策略 */
private array $strategies = [];
/** @var string 当前激活的策略名称 */
private string $activeStrategy = 'balanced';
/** @var array Provider 配置 */
private array $providers = [];
/**
* 获取单例实例
*/
public static function instance(): IntelligentRouter {
if ( self::$instance === null ) {
self::$instance = new self();
}
return self::$instance;
}
private function __construct() {
$this->register_default_strategies();
$this->load_providers();
$this->load_settings();
}
/**
* 注册默认策略
*/
private function register_default_strategies(): void {
// 复合策略(推荐)
$this->register_strategy( CompositeStrategy::create_balanced() ); // 平衡策略
$this->register_strategy( CompositeStrategy::create_performance() ); // 性能优先
$this->register_strategy( CompositeStrategy::create_economic() ); // 经济策略
// 基础策略
$this->register_strategy( new LoadBalancedStrategy() ); // 负载均衡
/**
* 允许第三方注册自定义路由策略
*
* @since 3.7.0
* @param IntelligentRouter $router 路由器实例
*/
do_action( 'wpmind_register_routing_strategies', $this );
}
/**
* 加载 Provider 配置
*/
private function load_providers(): void {
if ( function_exists( 'WPMind\\wpmind' ) ) {
$endpoints = \WPMind\wpmind()->get_custom_endpoints();
foreach ( $endpoints as $id => $config ) {
if ( ! empty( $config['enabled'] ) && ! empty( $config['api_key'] ) ) {
$this->providers[ $id ] = $config;
}
}
}
}
/**
* 加载路由设置
*/
private function load_settings(): void {
$settings = get_option( 'wpmind_routing_settings', array() );
$strategy = $settings['strategy'] ?? 'balanced';
// 验证策略是否存在,否则回退到默认
if ( ! isset( $this->strategies[ $strategy ] ) ) {
$strategy = 'balanced';
// 自动修复无效配置
if ( isset( $settings['strategy'] ) ) {
$settings['strategy'] = 'balanced';
update_option( 'wpmind_routing_settings', $settings );
}
}
$this->activeStrategy = $strategy;
}
/**
* 注册路由策略
*
* @param RoutingStrategyInterface $strategy 策略实例
*/
public function register_strategy( RoutingStrategyInterface $strategy ): void {
$this->strategies[ $strategy->get_name() ] = $strategy;
}
/**
* 获取所有已注册的策略
*
* @return array<string, array{name: string, display_name: string, description: string}>
*/
public function get_available_strategies(): array {
$result = [];
foreach ( $this->strategies as $name => $strategy ) {
$result[ $name ] = [
'name' => $strategy->get_name(),
'display_name' => $strategy->get_display_name(),
'description' => $strategy->get_description(),
];
}
return $result;
}
/**
* 设置当前策略
*
* @param string $strategyName 策略名称
* @return bool 是否设置成功
*/
public function set_strategy( string $strategyName ): bool {
if ( ! isset( $this->strategies[ $strategyName ] ) ) {
return false;
}
$this->activeStrategy = $strategyName;
// 保存设置
$settings = get_option( 'wpmind_routing_settings', [] );
$settings['strategy'] = $strategyName;
update_option( 'wpmind_routing_settings', $settings );
return true;
}
/**
* 获取当前策略名称
*/
public function get_current_strategy(): string {
return $this->activeStrategy;
}
/**
* 获取当前策略实例
*/
public function get_strategy( ?string $name = null ): ?RoutingStrategyInterface {
$name = $name ?? $this->activeStrategy;
// 如果请求的策略不存在,尝试回退到 'balanced'
if ( ! isset( $this->strategies[ $name ] ) && $name !== 'balanced' ) {
// 如果 balanced 也不存在,返回第一个可用策略
if ( isset( $this->strategies['balanced'] ) ) {
$name = 'balanced';
} else {
$name = array_key_first( $this->strategies );
}
}
return $this->strategies[ $name ] ?? null;
}
/**
* 路由请求到最佳 Provider
*
* @param RoutingContext|null $context 路由上下文
* @return string|null 选中的 Provider ID
*/
public function route( ?RoutingContext $context = null ): ?string {
$context = $context ?? RoutingContext::create();
$strategy = $this->get_strategy();
if ( $strategy === null ) {
// 无策略时,返回第一个可用的 Provider
return array_key_first( $this->providers );
}
// 如果有首选 Provider 且可用,优先使用
$preferred = $context->get_preferred_provider();
if ( $preferred !== null && isset( $this->providers[ $preferred ] ) ) {
if ( ! $context->is_excluded( $preferred ) ) {
return $preferred;
}
}
return $strategy->select_provider( $context, $this->providers );
}
/**
* 获取故障转移链
*
* 返回按策略排序的 Provider 列表
*
* @param RoutingContext|null $context 路由上下文
* @return array<string> Provider ID 列表
*/
public function get_failover_chain( ?RoutingContext $context = null ): array {
$context = $context ?? RoutingContext::create();
$strategy = $this->get_strategy();
if ( $strategy === null ) {
return array_keys( $this->providers );
}
$ranked = $strategy->rank_providers( $context, $this->providers );
// 如果有首选 Provider放在最前面
$preferred = $context->get_preferred_provider();
if ( $preferred !== null && in_array( $preferred, $ranked, true ) ) {
$ranked = array_values( array_diff( $ranked, [ $preferred ] ) );
array_unshift( $ranked, $preferred );
}
return $ranked;
}
/**
* 获取所有 Provider 的路由得分
*
* @param RoutingContext|null $context 路由上下文
* @return array<string, array{score: float, rank: int}>
*/
public function get_provider_scores( ?RoutingContext $context = null ): array {
$context = $context ?? RoutingContext::create();
$strategy = $this->get_strategy();
if ( $strategy === null ) {
return [];
}
$scores = [];
foreach ( $this->providers as $providerId => $config ) {
$scores[ $providerId ] = [
'score' => $strategy->calculate_score( $providerId, $context ),
'name' => $config['display_name'] ?? $providerId,
];
}
// 按得分排序并添加排名
uasort( $scores, fn( $a, $b ) => $b['score'] <=> $a['score'] );
$rank = 1;
foreach ( $scores as $providerId => &$data ) {
$data['rank'] = $rank++;
}
return $scores;
}
/**
* 获取路由状态摘要
*
* @return array 状态信息
*/
public function get_status_summary(): array {
$context = RoutingContext::create();
$strategy = $this->get_strategy();
return [
'active_strategy' => [
'name' => $this->activeStrategy,
'display_name' => $strategy?->get_display_name() ?? '未知',
'description' => $strategy?->get_description() ?? '',
],
'available_strategies' => $this->get_available_strategies(),
'provider_count' => count( $this->providers ),
'provider_scores' => $this->get_provider_scores( $context ),
'recommended' => $this->route( $context ),
'failover_chain' => $this->get_failover_chain( $context ),
];
}
/**
* 刷新路由器状态
*/
public function refresh(): void {
self::$instance = null;
self::instance();
}
/**
* 获取手动设置的 Provider 优先级
*
* @return array<string> Provider ID 列表,按优先级排序
*/
public function get_manual_priority(): array {
$settings = get_option( 'wpmind_routing_settings', [] );
return $settings['provider_priority'] ?? [];
}
/**
* 设置手动 Provider 优先级
*
* @param array<string> $priority Provider ID 列表,按优先级排序
* @return bool 是否设置成功
*/
public function set_manual_priority( array $priority ): bool {
// 验证所有 Provider ID 都有效
$valid_providers = array_keys( $this->providers );
$priority = array_filter( $priority, fn( $id ) => in_array( $id, $valid_providers, true ) );
$settings = get_option( 'wpmind_routing_settings', [] );
$settings['provider_priority'] = array_values( $priority );
return update_option( 'wpmind_routing_settings', $settings );
}
/**
* 清除手动优先级设置
*
* @return bool 是否清除成功
*/
public function clear_manual_priority(): bool {
$settings = get_option( 'wpmind_routing_settings', [] );
unset( $settings['provider_priority'] );
return update_option( 'wpmind_routing_settings', $settings );
}
/**
* 检查是否启用了手动优先级
*
* @return bool
*/
public function has_manual_priority(): bool {
$priority = $this->get_manual_priority();
return ! empty( $priority );
}
}