PluginProbe
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot / 4.8.2
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot v4.8.2
4.9.1 4.9.0 4.8.2 4.8.1 4.8.0 4.7.0 4.6.2 4.6.1 4.6.0 4.5.6 4.5.5 4.5.4 4.5.3 4.5.2 4.5.1 4.5.0 4.4.1 4.4.0 3.3.4 3.4.0 3.4.1 3.4.2 3.5.0 3.5.1 3.5.2 All 199 releases
betterdocs / includes / AI / ProviderFactory.php

ProviderFactory.php in BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot 4.8.2, at includes/AI/ProviderFactory.php

184 lines 5.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace WPDeveloper\BetterDocs\AI;
4
5 use WPDeveloper\BetterDocs\Core\Settings;
6 use WPDeveloper\BetterDocs\AI\Providers\OpenAIProvider;
7 use WPDeveloper\BetterDocs\AI\Providers\GeminiProvider;
8 use WPDeveloper\BetterDocs\AI\Providers\ClaudeProvider;
9 use WPDeveloper\BetterDocs\AI\Providers\DeepSeekProvider;
10 use WPDeveloper\BetterDocs\AI\Providers\OpenRouterProvider;
11
12 /**
13 * Resolves the active AI provider from settings and constructs it with the
14 * right per-platform API key and the global model. This is the single entry
15 * point the content-suite features use; they never name a concrete provider.
16 *
17 * @since 4.4.0
18 */
19 class ProviderFactory {
20
21 /**
22 * Per-platform API key settings are stored as ai_api_key_<platform>.
23 *
24 * Deliberately private: OpenAI does NOT follow this scheme (see
25 * OPENAI_KEY_FIELD), so hand-concatenating the prefix would silently read
26 * the wrong — always empty — setting for the default platform. Go through
27 * key_field_for() instead; it is the only sanctioned way to name a key field.
28 */
29 private const KEY_PREFIX = 'ai_api_key_';
30
31 /**
32 * OpenAI keeps the original single-provider field name. Write with AI has
33 * always been OpenAI-only, so the stored key is already the OpenAI key —
34 * reusing the name means existing installs need no migration and no user
35 * has to re-enter anything when multi-platform support lands.
36 */
37 const OPENAI_KEY_FIELD = 'ai_autowrite_api_key';
38
39 /**
40 * Settings key that holds the API key for a platform.
41 *
42 * @param string $platform
43 * @return string
44 */
45 public static function key_field_for( $platform ) {
46 return 'openai' === $platform ? self::OPENAI_KEY_FIELD : self::KEY_PREFIX . $platform;
47 }
48
49 /**
50 * @var Settings
51 */
52 private $settings;
53
54 public function __construct( Settings $settings ) {
55 $this->settings = $settings;
56 }
57
58 /**
59 * Platform id => provider class. Filterable so Pro / add-ons can register
60 * or replace providers without editing core.
61 *
62 * @return array<string,string>
63 */
64 public function provider_map() {
65 return apply_filters( 'betterdocs_ai_providers', array(
66 'openai' => OpenAIProvider::class,
67 'gemini' => GeminiProvider::class,
68 'claude' => ClaudeProvider::class,
69 'deepseek' => DeepSeekProvider::class,
70 'openrouter' => OpenRouterProvider::class,
71 ) );
72 }
73
74 /**
75 * Whether a platform id has a registered provider.
76 *
77 * @param string $platform
78 * @return bool
79 */
80 public function is_supported( $platform ) {
81 $map = $this->provider_map();
82 return isset( $map[ $platform ] );
83 }
84
85 /**
86 * Currently selected platform, defaulting to OpenAI.
87 *
88 * @return string
89 */
90 public function active_platform() {
91 $platform = (string) $this->settings->get( 'ai_platform', 'openai' );
92 return $this->is_supported( $platform ) ? $platform : 'openai';
93 }
94
95 /**
96 * Stored API key for a platform.
97 *
98 * @param string $platform
99 * @return string
100 */
101 public function api_key_for( $platform ) {
102 return (string) $this->settings->get( self::key_field_for( $platform ), '' );
103 }
104
105 /**
106 * Resolved global model for the active platform. Falls back through the
107 * legacy per-feature model and then the platform default, so a not-yet
108 * migrated install still resolves a valid model.
109 *
110 * @param string|null $platform
111 * @return string
112 */
113 public function active_model( $platform = null ) {
114 $platform = $platform ? $platform : $this->active_platform();
115 $model = (string) $this->settings->get( 'ai_model', '' );
116
117 if ( '' !== $model && ModelRegistry::has_model( $platform, $model ) ) {
118 return $model;
119 }
120
121 $legacy = (string) $this->settings->get( 'write_with_ai_model', '' );
122 if ( '' !== $legacy && ModelRegistry::has_model( $platform, $legacy ) ) {
123 return $legacy;
124 }
125
126 return ModelRegistry::default_model( $platform );
127 }
128
129 /**
130 * Build the provider for the active platform (or an explicit one).
131 *
132 * @param string|null $platform Optional platform override.
133 * @param string|null $model Optional model override.
134 * @return \WPDeveloper\BetterDocs\AI\Contracts\AIProvider
135 */
136 public function make( $platform = null, $model = null ) {
137 $platform = $platform ? $platform : $this->active_platform();
138 if ( ! $this->is_supported( $platform ) ) {
139 $platform = 'openai';
140 }
141
142 $map = $this->provider_map();
143 $class = $map[ $platform ];
144 $key = $this->api_key_for( $platform );
145
146 if ( null === $model ) {
147 $model = ( $platform === $this->active_platform() )
148 ? $this->active_model( $platform )
149 : ModelRegistry::default_model( $platform );
150 }
151
152 return new $class( $key, $model );
153 }
154
155 /**
156 * Build a provider with an explicit key/model — used by key validation
157 * before anything is persisted.
158 *
159 * @param string $platform
160 * @param string $api_key
161 * @param string $model
162 * @return \WPDeveloper\BetterDocs\AI\Contracts\AIProvider
163 */
164 public function make_with( $platform, $api_key, $model = '' ) {
165 if ( ! $this->is_supported( $platform ) ) {
166 $platform = 'openai';
167 }
168 $map = $this->provider_map();
169 $class = $map[ $platform ];
170 return new $class( $api_key, $model );
171 }
172
173 /**
174 * Validate a key for a platform.
175 *
176 * @param string $platform
177 * @param string $api_key
178 * @return array array( 'valid' => bool, 'message' => string )
179 */
180 public function validate( $platform, $api_key ) {
181 return $this->make_with( $platform, $api_key )->validate_key( $api_key );
182 }
183 }
184