PluginProbe
StockPack – Stock photos and AI images from Unsplash, Adobe Stock, Freepik and more / 3.7.0
StockPack – Stock photos and AI images from Unsplash, Adobe Stock, Freepik and more v3.7.0
3.7.0 3.6.0 3.6.1 3.5.2 trunk 2.0 2.1 2.2 2.3 2.4 2.4.1 2.4.2 2.4.3 2.5.0 2.5.1 2.5.2 2.5.3 2.5.4 2.5.5 2.5.6 2.5.7 2.6.0 2.6.1 3.0.0 3.0.1 All 71 releases
stockpack / src / class-stockpackadmin.php

class-stockpackadmin.php in StockPack – Stock photos and AI images from Unsplash, Adobe Stock, Freepik and more 3.7.0, at src/class-stockpackadmin.php

584 lines 21.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Class StockpackAdmin
5 *
6 * Handle the settings admin page
7 */
8 class StockpackAdmin {
9 /**
10 * @var Singleton The reference the *Singleton* instance of this class
11 */
12 private static $instance;
13
14 /**
15 * @var WeDevs_Settings_API
16 */
17 public $settings_api;
18
19 /**
20 * @var string plugin version
21 */
22 public $version = '3.7.0';
23
24 /**
25 * Returns the *Singleton* instance of this class.
26 *
27 * @return Singleton The *Singleton* instance.
28 */
29 public static function get_instance() {
30 if ( null === self::$instance ) {
31 self::$instance = new self();
32 }
33
34 return self::$instance;
35 }
36
37 /**
38 * Stockpack constructor.
39 */
40 protected function __construct() {
41 add_action( 'init', array( $this, 'init' ) );
42 }
43
44 /**
45 *
46 */
47 public function init() {
48 $this->actions();
49 $this->filters();
50 }
51
52 /**
53 *
54 */
55 public function actions() {
56 add_action( 'wp_loaded', array( $this, 'maybe_show_notice' ) );
57 add_action( 'admin_init', array( $this, 'register_settings' ) );
58 add_action( 'admin_menu', array( $this, 'register_settings_page' ) );
59 }
60
61 public function filters() {
62 add_filter( 'stockpack_download_timeout', array( $this, 'download_timeout' ), 10, 1 );
63 }
64
65 public function download_timeout( $limit ) {
66 $overwrite_limit = (int) $this->get_option( 'download_timeout', 'stockpack_debug' );
67 if ( $overwrite_limit > 0 ) {
68 return $overwrite_limit;
69 }
70
71 return $limit;
72 }
73
74 /**
75 * Register settings
76 */
77 public function register_settings() {
78
79 $this->settings_api = new WeDevs_Settings_API();
80 // remove settings scripts as we do not use the color picker
81 if(!(isset($_GET['page']) && $_GET['page'] === 'stockpack')) {
82 remove_action('admin_enqueue_scripts', array($this->settings_api, 'admin_enqueue_scripts'));
83 }
84
85 //set sections and fields
86 $this->settings_api->set_sections( $this->get_settings_sections() );
87 $this->settings_api->set_fields( $this->get_settings_fields() );
88
89 //initialize them
90 add_action( 'wsa_form_top_stockpack_basics', array( $this, 'credits_line' ) );
91
92 $this->settings_api->admin_init();
93 }
94
95 public function register_settings_page() {
96 $capability = apply_filters( 'stockpack_settings_capability', 'upload_files' );
97
98 add_options_page( __( 'StockPack', 'stockpack' ), __( 'StockPack', 'stockpack' ), $capability, 'stockpack',
99 array( $this, 'plugin_page' )
100 );
101 }
102
103 public function maybe_show_notice() {
104
105 add_action( 'admin_notices', array( $this, 'compatibility_notice' ) );
106 if ( ! PAnD::is_admin_notice_active( 'disable-media-notice-forever' ) ) {
107 return;
108 }
109 add_action( 'admin_init', array( 'PAnD', 'init' ) );
110
111 add_action( 'admin_notices', array( $this, 'media_notice' ) );
112
113 add_action( 'wsa_form_bottom_stockpack_debug', array( $this, 'debug_info' ) );
114 }
115
116 public function compatibility_notice() {
117 // all compatibility issues were resolved
118 }
119
120 public function media_notice() {
121 global $pagenow;
122 if ( $pagenow != 'upload.php' ) {
123 return;
124 }
125
126 $capability = apply_filters( 'stockpack_notices_capability', 'upload_files' );
127 if ( current_user_can( $capability ) ) {
128 echo '<div data-dismissible="disable-media-notice-forever" class="notice notice-warning is-dismissible">
129 <p>' . __( 'If you are looking for StockPack you will find it on the Media Tab when you use the WordPress uploader. Just go to a post or page and try to insert an image. You will see the StockPack tab at the top. You can read more here:', 'stockpack' ) . ' <a href="https://stockpack.co/blog/what-to-do-if-stockpack-tab-is-not-showing-up/">' . __( 'What to do if stockpack tab is not showing up', 'stockpack' ) . '</a></p>
130 </div>';
131 }
132
133 }
134
135 public function plugin_page() {
136
137 echo '<div class="wrap">';
138 $this->settings_api->show_navigation();
139 $this->settings_api->show_forms();
140 $link_text = esc_textarea( __( 'Get your token', 'stockpack' ) );
141 echo '<a class="license-key-link" href="https://stockpack.co/register" target="_blank">' . $link_text . '</a>';
142
143 echo '</div>';
144 }
145
146 public function get_featured_caption_setting() {
147 return $this->get_option( 'caption_featured_image', 'stockpack_advanced' );
148 }
149
150 /**
151 * @return mixed
152 */
153 public function get_api_key() {
154 return $this->get_option( 'auth_token', 'stockpack_basics' );
155 }
156
157 /**
158 * @return mixed
159 */
160 public function set_api_key( $token ) {
161 return $this->set_option( 'auth_token', 'stockpack_basics', $token );
162 }
163
164 public function debug_info() {
165 global $wp_version;
166 $theme = wp_get_theme();
167 $memory = $this->wc_let_to_num( WP_MEMORY_LIMIT );
168
169 if ( function_exists( 'memory_get_usage' ) ) {
170 $system_memory = $this->wc_let_to_num( @ini_get( 'memory_limit' ) );
171 $memory = max( $memory, $system_memory );
172 }
173 $data = [
174 'active_plugins' => get_option( 'active_plugins' ),
175 'theme' => $theme->name,
176 'wp_version' => $wp_version,
177 'token' => $this->get_api_key(),
178 'plugin_version' => $this->version,
179 'is_multisite' => is_multisite(),
180 'memory' => size_format( $memory ),
181 'server_info' => $this->wc_get_server_info()
182 ];
183
184 echo "<br><br/><i>".__('Copy this information when you write to support with a bug issue','stockpack')."</i><br/>";
185 echo "<textarea cols='80' rows='10'>" . json_encode( $data ) . "</textarea>";
186 }
187
188
189 /**
190 * WC function to convert php data to int
191 *
192 * @param $size
193 *
194 * @return int
195 */
196 private function wc_let_to_num( $size ) {
197 $l = substr( $size, - 1 );
198 $ret = (int) substr( $size, 0, - 1 );
199 switch ( strtoupper( $l ) ) {
200 case 'P':
201 $ret *= 1024;
202 // No break.
203 case 'T':
204 $ret *= 1024;
205 // No break.
206 case 'G':
207 $ret *= 1024;
208 // No break.
209 case 'M':
210 $ret *= 1024;
211 // No break.
212 case 'K':
213 $ret *= 1024;
214 // No break.
215 }
216
217 return $ret;
218 }
219
220 /**
221 * WC function to get server related info.
222 *
223 * @return array
224 */
225 private function wc_get_server_info() {
226 $server_data = array();
227
228 if ( ! empty( $_SERVER['SERVER_SOFTWARE'] ) ) {
229 $server_data['software'] = $_SERVER['SERVER_SOFTWARE']; // @phpcs:ignore
230 }
231
232 if ( function_exists( 'phpversion' ) ) {
233 $server_data['php_version'] = phpversion();
234 }
235
236 if ( function_exists( 'ini_get' ) ) {
237 $server_data['php_post_max_size'] = size_format( $this->wc_let_to_num( ini_get( 'post_max_size' ) ) );
238 $server_data['php_time_limt'] = ini_get( 'max_execution_time' );
239 $server_data['php_max_input_vars'] = ini_get( 'max_input_vars' );
240 $server_data['php_suhosin'] = extension_loaded( 'suhosin' ) ? 'Yes' : 'No';
241 }
242
243 $server_data['php_max_upload_size'] = size_format( wp_max_upload_size() );
244 $server_data['php_default_timezone'] = date_default_timezone_get();
245 $server_data['php_soap'] = class_exists( 'SoapClient' ) ? 'Yes' : 'No';
246 $server_data['php_fsockopen'] = function_exists( 'fsockopen' ) ? 'Yes' : 'No';
247 $server_data['php_curl'] = function_exists( 'curl_init' ) ? 'Yes' : 'No';
248
249 return $server_data;
250 }
251
252
253 /**
254 * @return array
255 */
256 private function get_settings_sections() {
257 return array(
258 array(
259 'id' => 'stockpack_basics',
260 'title' => __( 'General', 'stockpack' ),
261 ),
262 array(
263 'id' => 'stockpack_advanced',
264 'title' => __( 'Advanced', 'stockpack' ),
265 ),
266 array(
267 'id' => 'stockpack_debug',
268 'title' => __( 'Debug', 'stockpack' ),
269 ),
270 );
271 }
272
273 private function ai_models(): array {
274 $prices = StockPack::get_instance()->query->get_ai_prices();
275 $models = isset( $prices['models'] ) && is_array( $prices['models'] ) ? $prices['models'] : array();
276
277 if ( ! $models || ! $this->managed_credits() ) {
278 return $models;
279 }
280
281 $sellable = array_filter( $models, function ( $model ) {
282 return isset( $model['wallet_credits'] );
283 } );
284
285 return $sellable ?: $models;
286 }
287
288 private function ai_model_options(): array {
289 $options = array();
290 $managed = $this->managed_credits();
291
292 foreach ( $this->ai_models() as $key => $model ) {
293 if ( $managed ) {
294 $price = isset( $model['wallet_credits'] ) ? sprintf( ' (%s)', $this->format_credits( $model['wallet_credits'] ) ) : '';
295 } else {
296 $price = isset( $model['eur'] ) ? sprintf( ' (€%s)', rtrim( rtrim( number_format( (float) $model['eur'], 3 ), '0' ), '.' ) ) : '';
297 }
298
299 $options[ $key ] = ( isset( $model['label'] ) ? $model['label'] : $key ) . $price;
300 }
301
302 return $options;
303 }
304
305 private function ai_wallet(): array {
306 return StockPack::get_instance()->query->get_ai_wallet();
307 }
308
309 private function managed_credits(): bool {
310 $wallet = $this->ai_wallet();
311
312 return 'managed' === $wallet['mode'];
313 }
314
315 private function format_credits( $credits ): string {
316 $credits = (int) $credits;
317
318 return sprintf(
319 /* translators: %s: number of credits, already formatted */
320 _n( '%s credit', '%s credits', $credits, 'stockpack' ),
321 number_format_i18n( $credits )
322 );
323 }
324
325 public function credits_line() {
326 $wallet = $this->ai_wallet();
327
328 if ( 'byok' === $wallet['mode'] ) {
329 return;
330 }
331
332 if ( 'unavailable' === $wallet['mode'] ) {
333 printf(
334 '<p class="description stockpack-credits-line">%s <a href="%s" target="_blank" rel="noopener">%s</a> · <a href="%s" target="_blank" rel="noopener">%s</a></p>',
335 esc_html__( 'Image generation is not set up for this site yet. Connect your own Magnific key on stockpack.co, or buy StockPack credits.', 'stockpack' ),
336 esc_url( $wallet['connect_url'] ),
337 esc_html__( 'Connect Magnific', 'stockpack' ),
338 esc_url( $wallet['top_up_url'] ),
339 esc_html__( 'Top up credits', 'stockpack' )
340 );
341
342 return;
343 }
344
345 printf(
346 '<p class="description stockpack-credits-line">%s · <a href="%s" target="_blank" rel="noopener">%s</a></p>',
347 /* translators: %s: credit balance, already formatted */
348 esc_html( sprintf( __( 'Credits: %s', 'stockpack' ), $wallet['balance_text'] ) ),
349 esc_url( $wallet['top_up_url'] ),
350 esc_html__( 'Manage on stockpack.co', 'stockpack' )
351 );
352 }
353
354 private function ai_model_defaults(): array {
355 $defaults = array();
356
357 foreach ( $this->ai_models() as $key => $model ) {
358 if ( ! empty( $model['default'] ) ) {
359 $defaults[ $key ] = $key;
360 }
361 }
362
363 return $defaults;
364 }
365
366 private function ai_models_description(): string {
367 $all = count( $this->ai_models() );
368
369 if ( $this->managed_credits() ) {
370 return sprintf(
371 /* translators: %d: number of models sellable on StockPack credits */
372 _n(
373 'Choose which models appear in the generate dropdown. %d is available on StockPack credits and its price is per image. Models Magnific does not let us resell stay available on your own Magnific key.',
374 'Choose which models appear in the generate dropdown. %d are available on StockPack credits and prices are per image. Models Magnific does not let us resell stay available on your own Magnific key.',
375 $all,
376 'stockpack'
377 ),
378 $all
379 );
380 }
381
382 return sprintf(
383 /* translators: %d: total number of models offered by the provider */
384 __( 'Choose which models appear in the generate dropdown. %d are available and prices are per image, charged to the Magnific account you connect. Cheaper models are good for trying out a prompt; switch to a dearer one once you are happy with it.', 'stockpack' ),
385 $all
386 );
387 }
388
389 /**
390 * @return array
391 */
392 private function get_settings_fields() {
393 return array(
394 'stockpack_basics' => array(
395 array(
396 'name' => 'auth_token',
397 'label' => __( 'Token', 'stockpack' ),
398 'desc' => __( 'This is the token that is used for authentication', 'stockpack' ),
399 'type' => 'text',
400 'default' => '',
401 'size' => 'validate-stockpack-key regular' //small hack to add class
402 ),
403 array(
404 'name' => 'safe_search',
405 'label' => __( 'Apply safe search', 'stockpack' ),
406 'desc' => __( 'Some providers support this mode to prevent nude images to show up in the search', 'stockpack' ),
407 'options' => array(
408 'yes' => __( 'Yes', 'stockpack' ),
409 'no' => __( 'No', 'stockpack' )
410 ),
411 'type' => 'radio',
412 'default' => 'yes',
413 ),
414 array(
415 'name' => 'providers',
416 'label' => __( 'Providers available', 'stockpack' ),
417 'desc' => __( 'Select providers you want to use in the select', 'stockpack' ),
418 'options' => array(
419 'Adobe Stock' => __( 'Adobe Stock', 'stockpack' ),
420 'Deposit Photos' => __( 'Deposit Photos', 'stockpack' ),
421 'Freepik' => __( 'Freepik (Magnific)', 'stockpack' ),
422 'Magnific AI' => __( 'Magnific AI (generate)', 'stockpack' ),
423 'Getty' => __( 'Getty Images', 'stockpack' ),
424 'iStock' => __( 'iStock', 'stockpack' ),
425 'Pixabay' => __( 'Pixabay', 'stockpack' ),
426 'Pexels' => __( 'Pexels', 'stockpack' ),
427 'Unsplash' => __( 'Unsplash', 'stockpack' ),
428 ),
429 'size' => 'add-links-to-providers',
430 'type' => 'multicheck',
431 'default' => [
432 'Adobe Stock'=> 'Adobe Stock',
433 'Deposit Photos'=> 'Deposit Photos',
434 'Freepik'=> 'Freepik',
435 'Magnific AI'=> 'Magnific AI',
436 'Getty'=> 'Getty',
437 'iStock'=> 'iStock',
438 'Pixabay' => 'Pixabay',
439 'Pexels' => 'Pexels',
440 'Unsplash' => 'Unsplash',
441 ],
442 ),
443 array(
444 'name' => 'ai_models',
445 'label' => __( 'AI models available', 'stockpack' ),
446 'desc' => $this->ai_models_description(),
447 'options' => $this->ai_model_options(),
448 'type' => 'multicheck',
449 'default' => $this->ai_model_defaults(),
450 ),
451 array(
452 'name' => 'file_name_change',
453 'label' => __( 'Enable file name change', 'stockpack' ),
454 'desc' => __( 'You can set the desired filename prior to download. This is a good SEO idea if you want it, but it\'s a small extra step', 'stockpack' ),
455 'options' => array(
456 'yes' => __( 'Yes', 'stockpack' ),
457 'no' => __( 'No', 'stockpack' )
458 ),
459 'type' => 'radio',
460 'default' => 'no',
461 )
462 ),
463 'stockpack_advanced' => array(
464 array(
465 'name' => 'caption_premium_providers',
466 'label' => __( 'Enable premium providers caption', 'stockpack' ),
467 'desc' => __( 'You can enable automatic caption for premium providers if you want to', 'stockpack' ),
468 'options' => array(
469 'yes' => __( 'Yes', 'stockpack' ),
470 'no' => __( 'No', 'stockpack' )
471 ),
472 'type' => 'radio',
473 'default' => 'no',
474 ),
475 array(
476 'name' => 'caption_standard_fields',
477 'label' => __( 'Enable caption fields', 'stockpack' ),
478 'desc' => __( 'You can enable additional fields for images that you can use to standardize captions. This is generally used to provide credits.', 'stockpack' ),
479 'options' => array(
480 'yes' => __( 'Yes', 'stockpack' ),
481 'no' => __( 'No', 'stockpack' )
482 ),
483 'type' => 'radio',
484 'default' => 'no',
485 ),
486 array(
487 'name' => 'caption_featured_image',
488 'label' => __( 'Enable featured image caption', 'stockpack' ),
489 'desc' => __( 'You can enable captions for featured images to be appended. If you want to use this for non stockpack images, you also need the above setting.', 'stockpack' ),
490 'options' => array(
491 'yes' => __( 'Yes', 'stockpack' ),
492 'no' => __( 'No', 'stockpack' )
493 ),
494 'type' => 'radio',
495 'default' => 'no',
496 ),
497 array(
498 'name' => 'license_state',
499 'label' => __( 'Search with authorization', 'stockpack' ),
500 'desc' => __( 'Providers that support oauth can get the license state for all images directly. You see it in the sidebar. The downside is that the searches are slower', 'stockpack' ),
501 'options' => array(
502 'yes' => __( 'Yes', 'stockpack' ),
503 'no' => __( 'No', 'stockpack' )
504 ),
505 'type' => 'radio',
506 'default' => 'no',
507 ),
508 array(
509 'name' => 'add_license_state_to_filename',
510 'label' => __( 'Update file name with provider name and license state for premium providers', 'stockpack' ),
511 'desc' => __( 'By adding details to the image file name you can use unlicensed images as placeholders and if you use Gutenberg you can later license those images directly via StockBlock, the Gutenberg module from StockPack', 'stockpack' ),
512 'options' => array(
513 'yes' => __( 'Yes', 'stockpack' ),
514 'no' => __( 'No', 'stockpack' )
515 ),
516 'type' => 'radio',
517 'default' => 'no',
518 ),
519 ),
520 'stockpack_debug' => array(
521 array(
522 'name' => 'download_timeout',
523 'label' => __( 'Download timeout in seconds', 'stockpack' ),
524 'desc' => __( 'If you have issues downloading the images, increasing this might help', 'stockpack' ),
525 'type' => 'number',
526 'default' => 30,
527 ),
528 array(
529 'name' => 'url_debugging',
530 'label' => __( 'Enable URL debugging', 'stockpack' ),
531 'desc' => __( 'This will log all external calls made and add them to wp-content/debug.log. Make sure you have space on the disk (a few hundred megabytes) and only keep this enabled for short periods of time', 'stockpack' ),
532 'options' => array(
533 'yes' => __( 'Yes', 'stockpack' ),
534 'no' => __( 'No', 'stockpack' )
535 ),
536 'type' => 'radio',
537 'default' => 'no',
538 ),
539 )
540 );
541 }
542
543 /**
544 * Get the value of a settings field
545 *
546 * @param string $option settings field name
547 * @param string $section the section name this field belongs to
548 * @param string $default default text if it's not found
549 *
550 * @return mixed
551 */
552 private function get_option( $option, $section, $default = '' ) {
553
554 $options = get_option( $section, array() );
555
556 if ( isset( $options[ $option ] ) ) {
557 return $options[ $option ];
558 }
559
560 return $default;
561 }
562
563 /**
564 * Set the value of a settings field
565 *
566 * @param string $option settings field name
567 * @param string $section the section name this field belongs to
568 * @param string $value
569 *
570 * @return mixed
571 */
572 private function set_option( $option, $section, $value ) {
573
574 $options = get_option( $section, array() );
575 if ( ! is_array( $options ) ) {
576 $options = array();
577 }
578
579 $options[ $option ] = $value;
580
581 update_option( $section, $options );
582 }
583 }
584