PluginProbe
BotWriter – AI Writer & SEO Content Generator / 3.4.4
BotWriter – AI Writer & SEO Content Generator v3.4.4
3.4.10 3.4.9 3.4.8 3.4.7 3.4.6 3.4.4 3.4.2 3.4.1 3.4.0 3.3.9 3.3.8 3.3.7 3.3.6 3.3.5 3.3.4 3.3.3 3.3.2 3.3.1 3.3.0 3.2.8 trunk 1.3.0 1.3.1 1.3.2 1.3.3 All 51 releases
botwriter / includes / image-models.php

image-models.php in BotWriter – AI Writer & SEO Content Generator 3.4.4, at includes/image-models.php

287 lines 8.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * BotWriter Image Models Manager
4 *
5 * Handles loading/storing image provider models from a dedicated JSON catalog.
6 *
7 * @package BotWriter
8 */
9
10 if (!defined('ABSPATH')) {
11 exit;
12 }
13
14 if (!defined('BOTWRITER_IMAGE_MODELS_OPTION')) {
15 define('BOTWRITER_IMAGE_MODELS_OPTION', 'botwriter_image_models_data');
16 }
17
18 /**
19 * Fallback catalog used when JSON file is unavailable.
20 *
21 * @return array
22 */
23 function botwriter_get_image_models_fallback_catalog() {
24 return array(
25 'version' => '1.0.0',
26 'updated' => gmdate('Y-m-d'),
27 'providers' => array(
28 'dalle' => array(
29 'default' => 'gpt-image-1',
30 'groups' => array(
31 'GPT Image' => array(
32 'gpt-image-1' => 'GPT Image 1',
33 ),
34 ),
35 'all_models' => array(),
36 ),
37 'gemini' => array(
38 'default' => 'gemini-2.5-flash-image',
39 'groups' => array(
40 'Gemini Image' => array(
41 'gemini-2.5-flash-image' => 'Gemini 2.5 Flash Image',
42 ),
43 ),
44 'all_models' => array(),
45 ),
46 'fal' => array(
47 'default' => 'fal-ai/flux-pro/v1.1',
48 'groups' => array(
49 'Fal.ai' => array(
50 'fal-ai/flux-pro/v1.1' => 'Flux Pro v1.1',
51 ),
52 ),
53 'all_models' => array(),
54 ),
55 'replicate' => array(
56 'default' => 'black-forest-labs/flux-1.1-pro',
57 'groups' => array(
58 'Replicate' => array(
59 'black-forest-labs/flux-1.1-pro' => 'Flux 1.1 Pro',
60 ),
61 ),
62 'all_models' => array(),
63 ),
64 'stability' => array(
65 'default' => 'sd3.5-large-turbo',
66 'groups' => array(
67 'Stability' => array(
68 'sd3.5-large-turbo' => 'SD 3.5 Large Turbo',
69 ),
70 ),
71 'all_models' => array(),
72 ),
73 'cloudflare' => array(
74 'default' => 'flux-1-schnell',
75 'groups' => array(
76 'Cloudflare' => array(
77 'flux-1-schnell' => 'FLUX.1 Schnell',
78 ),
79 ),
80 'all_models' => array(),
81 ),
82 'stockphoto' => array(
83 'default' => 'random',
84 'groups' => array(
85 'Stock Photo' => array(
86 'random' => 'Random (auto rotate)',
87 'pixabay' => 'Pixabay',
88 'pexels' => 'Pexels',
89 'unsplash' => 'Unsplash',
90 'openverse' => 'Openverse',
91 ),
92 ),
93 'all_models' => array(),
94 ),
95 'none' => array(
96 'default' => 'none',
97 'groups' => array(
98 'Disabled' => array(
99 'none' => 'No Image Generation',
100 ),
101 ),
102 'all_models' => array(),
103 ),
104 ),
105 );
106 }
107
108 /**
109 * Load default image models from JSON file.
110 *
111 * @return array
112 */
113 function botwriter_load_default_image_models() {
114 $json_file = plugin_dir_path(dirname(__FILE__)) . 'image-models-default.json';
115
116 if (!file_exists($json_file)) {
117 return botwriter_get_image_models_fallback_catalog();
118 }
119
120 $json_content = file_get_contents($json_file);
121 if ($json_content === false) {
122 return botwriter_get_image_models_fallback_catalog();
123 }
124
125 $models_data = json_decode($json_content, true);
126 if (json_last_error() !== JSON_ERROR_NONE || !is_array($models_data)) {
127 return botwriter_get_image_models_fallback_catalog();
128 }
129
130 if (empty($models_data['providers']) || !is_array($models_data['providers'])) {
131 return botwriter_get_image_models_fallback_catalog();
132 }
133
134 return $models_data;
135 }
136
137 /**
138 * Get persisted image models data, initialized from JSON if needed.
139 *
140 * @return array
141 */
142 function botwriter_get_image_models_data() {
143 $models_data = get_option(BOTWRITER_IMAGE_MODELS_OPTION);
144
145 if (empty($models_data) || !is_array($models_data) || empty($models_data['providers'])) {
146 $models_data = botwriter_load_default_image_models();
147 update_option(BOTWRITER_IMAGE_MODELS_OPTION, $models_data);
148 }
149
150 return $models_data;
151 }
152
153 /**
154 * Get grouped image models for a provider.
155 *
156 * @param string $provider Provider slug.
157 * @return array
158 */
159 function botwriter_get_provider_image_models($provider) {
160 $provider = sanitize_key((string) $provider);
161 $models_data = botwriter_get_image_models_data();
162
163 if (empty($models_data['providers'][$provider]['groups']) || !is_array($models_data['providers'][$provider]['groups'])) {
164 return array();
165 }
166
167 return $models_data['providers'][$provider]['groups'];
168 }
169
170 /**
171 * Get a flattened map of image models for a provider.
172 *
173 * @param string $provider Provider slug.
174 * @return array
175 */
176 function botwriter_get_provider_image_models_flat($provider) {
177 $grouped = botwriter_get_provider_image_models($provider);
178 if (empty($grouped) || !is_array($grouped)) {
179 return array();
180 }
181
182 $flat = array();
183 foreach ($grouped as $group_models) {
184 if (!is_array($group_models)) {
185 continue;
186 }
187
188 foreach ($group_models as $model_id => $model_label) {
189 $flat[(string) $model_id] = (string) $model_label;
190 }
191 }
192
193 return $flat;
194 }
195
196 /**
197 * Get provider default image model.
198 *
199 * @param string $provider Provider slug.
200 * @return string
201 */
202 function botwriter_get_provider_default_image_model($provider) {
203 $provider = sanitize_key((string) $provider);
204 $models_data = botwriter_get_image_models_data();
205
206 if (!empty($models_data['providers'][$provider]['default'])) {
207 return (string) $models_data['providers'][$provider]['default'];
208 }
209
210 return '';
211 }
212
213 /**
214 * Normalize an image model against the provider catalog.
215 *
216 * @param string $provider Provider slug.
217 * @param string $model Model value to normalize.
218 * @return string
219 */
220 function botwriter_normalize_image_model($provider, $model) {
221 $provider = sanitize_key((string) $provider);
222 $default_model = (string) botwriter_get_provider_default_image_model($provider);
223
224 if ($provider === 'stockphoto') {
225 $model = sanitize_key((string) $model);
226 $valid_stock_models = array('pixabay', 'pexels', 'unsplash', 'openverse', 'random');
227
228 if (in_array($model, $valid_stock_models, true)) {
229 return $model;
230 }
231
232 return 'random';
233 }
234 if ($provider === 'none') {
235 return 'none';
236 }
237
238 if ($default_model === '') {
239 $default_model = 'gpt-image-1';
240 }
241
242 $model = trim((string) $model);
243 if ($model === '') {
244 return $default_model;
245 }
246
247 if ($provider === 'gemini') {
248 $gemini_aliases = array(
249 'gemini-2.0-flash-preview-image-generation' => 'gemini-2.5-flash-image',
250 'gemini-2.0-flash-exp-image-generation' => 'gemini-2.5-flash-image',
251 'gemini-2.0-flash-image' => 'gemini-2.5-flash-image',
252 'gemini-2.5-flash-image-preview' => 'gemini-2.5-flash-image',
253 'gemini-3.1-flash-image' => 'gemini-3.1-flash-image-preview',
254 'gemini-3-pro-image' => 'gemini-3-pro-image-preview',
255 );
256
257 $model_lc = strtolower($model);
258 if (isset($gemini_aliases[$model_lc])) {
259 $model = $gemini_aliases[$model_lc];
260 } else {
261 $model = $model_lc;
262 }
263 }
264
265 $valid_models = array_keys(botwriter_get_provider_image_models_flat($provider));
266 if (!empty($valid_models) && in_array($model, $valid_models, true)) {
267 return $model;
268 }
269
270 return $default_model;
271 }
272
273 /**
274 * Return option name used to store the model for an image provider.
275 *
276 * @param string $provider Provider slug.
277 * @return string
278 */
279 function botwriter_get_image_model_option_name($provider) {
280 $provider = sanitize_key((string) $provider);
281 if ($provider === 'gemini') {
282 return 'botwriter_gemini_image_model';
283 }
284
285 return "botwriter_{$provider}_model";
286 }
287