| 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.2.4'; |
| 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 |
$this->settings_api->admin_init(); |
| 91 |
} |
| 92 |
|
| 93 |
public function register_settings_page() { |
| 94 |
$capability = apply_filters( 'stockpack_settings_capability', 'upload_files' ); |
| 95 |
|
| 96 |
add_options_page( __( 'StockPack', 'stockpack' ), __( 'StockPack', 'stockpack' ), $capability, 'stockpack', |
| 97 |
array( $this, 'plugin_page' ) |
| 98 |
); |
| 99 |
} |
| 100 |
|
| 101 |
public function maybe_show_notice() { |
| 102 |
|
| 103 |
add_action( 'admin_notices', array( $this, 'compatibility_notice' ) ); |
| 104 |
if ( ! PAnD::is_admin_notice_active( 'disable-media-notice-forever' ) ) { |
| 105 |
return; |
| 106 |
} |
| 107 |
add_action( 'admin_init', array( 'PAnD', 'init' ) ); |
| 108 |
|
| 109 |
add_action( 'admin_notices', array( $this, 'media_notice' ) ); |
| 110 |
|
| 111 |
add_action( 'wsa_form_bottom_stockpack_debug', array( $this, 'debug_info' ) ); |
| 112 |
} |
| 113 |
|
| 114 |
public function compatibility_notice() { |
| 115 |
// all compatibility issues were resolved |
| 116 |
} |
| 117 |
|
| 118 |
public function media_notice() { |
| 119 |
global $pagenow; |
| 120 |
if ( $pagenow != 'upload.php' ) { |
| 121 |
return; |
| 122 |
} |
| 123 |
|
| 124 |
$capability = apply_filters( 'stockpack_notices_capability', 'upload_files' ); |
| 125 |
if ( current_user_can( $capability ) ) { |
| 126 |
echo '<div data-dismissible="disable-media-notice-forever" class="notice notice-warning is-dismissible"> |
| 127 |
<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> |
| 128 |
</div>'; |
| 129 |
} |
| 130 |
|
| 131 |
} |
| 132 |
|
| 133 |
public function plugin_page() { |
| 134 |
|
| 135 |
echo '<div class="wrap">'; |
| 136 |
$this->settings_api->show_navigation(); |
| 137 |
$this->settings_api->show_forms(); |
| 138 |
$link_text = esc_textarea( __( 'Get your token', 'stockpack' ) ); |
| 139 |
echo '<a class="license-key-link" href="https://stockpack.co/register" target="_blank">' . $link_text . '</a>'; |
| 140 |
|
| 141 |
echo '</div>'; |
| 142 |
} |
| 143 |
|
| 144 |
public function get_featured_caption_setting() { |
| 145 |
return $this->get_option( 'caption_featured_image', 'stockpack_advanced' ); |
| 146 |
} |
| 147 |
|
| 148 |
/** |
| 149 |
* @return mixed |
| 150 |
*/ |
| 151 |
public function get_api_key() { |
| 152 |
return $this->get_option( 'auth_token', 'stockpack_basics' ); |
| 153 |
} |
| 154 |
|
| 155 |
/** |
| 156 |
* @return mixed |
| 157 |
*/ |
| 158 |
public function set_api_key( $token ) { |
| 159 |
return $this->set_option( 'auth_token', 'stockpack_basics', $token ); |
| 160 |
} |
| 161 |
|
| 162 |
public function debug_info() { |
| 163 |
global $wp_version; |
| 164 |
$theme = wp_get_theme(); |
| 165 |
$memory = $this->wc_let_to_num( WP_MEMORY_LIMIT ); |
| 166 |
|
| 167 |
if ( function_exists( 'memory_get_usage' ) ) { |
| 168 |
$system_memory = $this->wc_let_to_num( @ini_get( 'memory_limit' ) ); |
| 169 |
$memory = max( $memory, $system_memory ); |
| 170 |
} |
| 171 |
$data = [ |
| 172 |
'active_plugins' => get_option( 'active_plugins' ), |
| 173 |
'theme' => $theme->name, |
| 174 |
'wp_version' => $wp_version, |
| 175 |
'token' => $this->get_api_key(), |
| 176 |
'plugin_version' => $this->version, |
| 177 |
'is_multisite' => is_multisite(), |
| 178 |
'memory' => size_format( $memory ), |
| 179 |
'server_info' => $this->wc_get_server_info() |
| 180 |
]; |
| 181 |
|
| 182 |
echo "<br><br/><i>".__('Copy this information when you write to support with a bug issue','stockpack')."</i><br/>"; |
| 183 |
echo "<textarea cols='80' rows='10'>" . json_encode( $data ) . "</textarea>"; |
| 184 |
} |
| 185 |
|
| 186 |
|
| 187 |
/** |
| 188 |
* WC function to convert php data to int |
| 189 |
* |
| 190 |
* @param $size |
| 191 |
* |
| 192 |
* @return int |
| 193 |
*/ |
| 194 |
private function wc_let_to_num( $size ) { |
| 195 |
$l = substr( $size, - 1 ); |
| 196 |
$ret = (int) substr( $size, 0, - 1 ); |
| 197 |
switch ( strtoupper( $l ) ) { |
| 198 |
case 'P': |
| 199 |
$ret *= 1024; |
| 200 |
// No break. |
| 201 |
case 'T': |
| 202 |
$ret *= 1024; |
| 203 |
// No break. |
| 204 |
case 'G': |
| 205 |
$ret *= 1024; |
| 206 |
// No break. |
| 207 |
case 'M': |
| 208 |
$ret *= 1024; |
| 209 |
// No break. |
| 210 |
case 'K': |
| 211 |
$ret *= 1024; |
| 212 |
// No break. |
| 213 |
} |
| 214 |
|
| 215 |
return $ret; |
| 216 |
} |
| 217 |
|
| 218 |
/** |
| 219 |
* WC function to get server related info. |
| 220 |
* |
| 221 |
* @return array |
| 222 |
*/ |
| 223 |
private function wc_get_server_info() { |
| 224 |
$server_data = array(); |
| 225 |
|
| 226 |
if ( ! empty( $_SERVER['SERVER_SOFTWARE'] ) ) { |
| 227 |
$server_data['software'] = $_SERVER['SERVER_SOFTWARE']; // @phpcs:ignore |
| 228 |
} |
| 229 |
|
| 230 |
if ( function_exists( 'phpversion' ) ) { |
| 231 |
$server_data['php_version'] = phpversion(); |
| 232 |
} |
| 233 |
|
| 234 |
if ( function_exists( 'ini_get' ) ) { |
| 235 |
$server_data['php_post_max_size'] = size_format( $this->wc_let_to_num( ini_get( 'post_max_size' ) ) ); |
| 236 |
$server_data['php_time_limt'] = ini_get( 'max_execution_time' ); |
| 237 |
$server_data['php_max_input_vars'] = ini_get( 'max_input_vars' ); |
| 238 |
$server_data['php_suhosin'] = extension_loaded( 'suhosin' ) ? 'Yes' : 'No'; |
| 239 |
} |
| 240 |
|
| 241 |
$server_data['php_max_upload_size'] = size_format( wp_max_upload_size() ); |
| 242 |
$server_data['php_default_timezone'] = date_default_timezone_get(); |
| 243 |
$server_data['php_soap'] = class_exists( 'SoapClient' ) ? 'Yes' : 'No'; |
| 244 |
$server_data['php_fsockopen'] = function_exists( 'fsockopen' ) ? 'Yes' : 'No'; |
| 245 |
$server_data['php_curl'] = function_exists( 'curl_init' ) ? 'Yes' : 'No'; |
| 246 |
|
| 247 |
return $server_data; |
| 248 |
} |
| 249 |
|
| 250 |
|
| 251 |
/** |
| 252 |
* @return array |
| 253 |
*/ |
| 254 |
private function get_settings_sections() { |
| 255 |
return array( |
| 256 |
array( |
| 257 |
'id' => 'stockpack_basics', |
| 258 |
'title' => __( 'General', 'stockpack' ), |
| 259 |
), |
| 260 |
array( |
| 261 |
'id' => 'stockpack_advanced', |
| 262 |
'title' => __( 'Advanced', 'stockpack' ), |
| 263 |
), |
| 264 |
array( |
| 265 |
'id' => 'stockpack_debug', |
| 266 |
'title' => __( 'Debug', 'stockpack' ), |
| 267 |
), |
| 268 |
); |
| 269 |
} |
| 270 |
|
| 271 |
private function ai_models(): array { |
| 272 |
$prices = StockPack::get_instance()->query->get_ai_prices(); |
| 273 |
|
| 274 |
return isset( $prices['models'] ) && is_array( $prices['models'] ) ? $prices['models'] : array(); |
| 275 |
} |
| 276 |
|
| 277 |
private function ai_model_options(): array { |
| 278 |
$options = array(); |
| 279 |
|
| 280 |
foreach ( $this->ai_models() as $key => $model ) { |
| 281 |
$price = isset( $model['eur'] ) ? sprintf( ' (€%s)', rtrim( rtrim( number_format( (float) $model['eur'], 3 ), '0' ), '.' ) ) : ''; |
| 282 |
|
| 283 |
$options[ $key ] = ( isset( $model['label'] ) ? $model['label'] : $key ) . $price; |
| 284 |
} |
| 285 |
|
| 286 |
return $options; |
| 287 |
} |
| 288 |
|
| 289 |
private function ai_model_defaults(): array { |
| 290 |
$defaults = array(); |
| 291 |
|
| 292 |
foreach ( $this->ai_models() as $key => $model ) { |
| 293 |
if ( ! empty( $model['default'] ) ) { |
| 294 |
$defaults[ $key ] = $key; |
| 295 |
} |
| 296 |
} |
| 297 |
|
| 298 |
return $defaults; |
| 299 |
} |
| 300 |
|
| 301 |
private function ai_models_description(): string { |
| 302 |
$all = count( $this->ai_models() ); |
| 303 |
|
| 304 |
return sprintf( |
| 305 |
/* translators: %d: total number of models offered by the provider */ |
| 306 |
__( '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' ), |
| 307 |
$all |
| 308 |
); |
| 309 |
} |
| 310 |
|
| 311 |
/** |
| 312 |
* @return array |
| 313 |
*/ |
| 314 |
private function get_settings_fields() { |
| 315 |
return array( |
| 316 |
'stockpack_basics' => array( |
| 317 |
array( |
| 318 |
'name' => 'auth_token', |
| 319 |
'label' => __( 'Token', 'stockpack' ), |
| 320 |
'desc' => __( 'This is the token that is used for authentication', 'stockpack' ), |
| 321 |
'type' => 'text', |
| 322 |
'default' => '', |
| 323 |
'size' => 'validate-stockpack-key regular' //small hack to add class |
| 324 |
), |
| 325 |
array( |
| 326 |
'name' => 'safe_search', |
| 327 |
'label' => __( 'Apply safe search', 'stockpack' ), |
| 328 |
'desc' => __( 'Some providers support this mode to prevent nude images to show up in the search', 'stockpack' ), |
| 329 |
'options' => array( |
| 330 |
'yes' => __( 'Yes', 'stockpack' ), |
| 331 |
'no' => __( 'No', 'stockpack' ) |
| 332 |
), |
| 333 |
'type' => 'radio', |
| 334 |
'default' => 'yes', |
| 335 |
), |
| 336 |
array( |
| 337 |
'name' => 'providers', |
| 338 |
'label' => __( 'Providers available', 'stockpack' ), |
| 339 |
'desc' => __( 'Select providers you want to use in the select', 'stockpack' ), |
| 340 |
'options' => array( |
| 341 |
'Adobe Stock' => __( 'Adobe Stock', 'stockpack' ), |
| 342 |
'Deposit Photos' => __( 'Deposit Photos', 'stockpack' ), |
| 343 |
'Freepik' => __( 'Freepik (Magnific)', 'stockpack' ), |
| 344 |
'Magnific AI' => __( 'Magnific AI (generate)', 'stockpack' ), |
| 345 |
'Getty' => __( 'Getty Images', 'stockpack' ), |
| 346 |
'iStock' => __( 'iStock', 'stockpack' ), |
| 347 |
'Pixabay' => __( 'Pixabay', 'stockpack' ), |
| 348 |
'Pexels' => __( 'Pexels', 'stockpack' ), |
| 349 |
'Unsplash' => __( 'Unsplash', 'stockpack' ), |
| 350 |
), |
| 351 |
'size' => 'add-links-to-providers', |
| 352 |
'type' => 'multicheck', |
| 353 |
'default' => [ |
| 354 |
'Adobe Stock'=> 'Adobe Stock', |
| 355 |
'Deposit Photos'=> 'Deposit Photos', |
| 356 |
'Freepik'=> 'Freepik', |
| 357 |
'Magnific AI'=> 'Magnific AI', |
| 358 |
'Getty'=> 'Getty', |
| 359 |
'iStock'=> 'iStock', |
| 360 |
'Pixabay' => 'Pixabay', |
| 361 |
'Pexels' => 'Pexels', |
| 362 |
'Unsplash' => 'Unsplash', |
| 363 |
], |
| 364 |
), |
| 365 |
array( |
| 366 |
'name' => 'ai_models', |
| 367 |
'label' => __( 'AI models available', 'stockpack' ), |
| 368 |
'desc' => $this->ai_models_description(), |
| 369 |
'options' => $this->ai_model_options(), |
| 370 |
'type' => 'multicheck', |
| 371 |
'default' => $this->ai_model_defaults(), |
| 372 |
), |
| 373 |
array( |
| 374 |
'name' => 'file_name_change', |
| 375 |
'label' => __( 'Enable file name change', 'stockpack' ), |
| 376 |
'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' ), |
| 377 |
'options' => array( |
| 378 |
'yes' => __( 'Yes', 'stockpack' ), |
| 379 |
'no' => __( 'No', 'stockpack' ) |
| 380 |
), |
| 381 |
'type' => 'radio', |
| 382 |
'default' => 'no', |
| 383 |
) |
| 384 |
), |
| 385 |
'stockpack_advanced' => array( |
| 386 |
array( |
| 387 |
'name' => 'caption_premium_providers', |
| 388 |
'label' => __( 'Enable premium providers caption', 'stockpack' ), |
| 389 |
'desc' => __( 'You can enable automatic caption for premium providers if you want to', 'stockpack' ), |
| 390 |
'options' => array( |
| 391 |
'yes' => __( 'Yes', 'stockpack' ), |
| 392 |
'no' => __( 'No', 'stockpack' ) |
| 393 |
), |
| 394 |
'type' => 'radio', |
| 395 |
'default' => 'no', |
| 396 |
), |
| 397 |
array( |
| 398 |
'name' => 'caption_standard_fields', |
| 399 |
'label' => __( 'Enable caption fields', 'stockpack' ), |
| 400 |
'desc' => __( 'You can enable additional fields for images that you can use to standardize captions. This is generally used to provide credits.', 'stockpack' ), |
| 401 |
'options' => array( |
| 402 |
'yes' => __( 'Yes', 'stockpack' ), |
| 403 |
'no' => __( 'No', 'stockpack' ) |
| 404 |
), |
| 405 |
'type' => 'radio', |
| 406 |
'default' => 'no', |
| 407 |
), |
| 408 |
array( |
| 409 |
'name' => 'caption_featured_image', |
| 410 |
'label' => __( 'Enable featured image caption', 'stockpack' ), |
| 411 |
'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' ), |
| 412 |
'options' => array( |
| 413 |
'yes' => __( 'Yes', 'stockpack' ), |
| 414 |
'no' => __( 'No', 'stockpack' ) |
| 415 |
), |
| 416 |
'type' => 'radio', |
| 417 |
'default' => 'no', |
| 418 |
), |
| 419 |
array( |
| 420 |
'name' => 'license_state', |
| 421 |
'label' => __( 'Search with authorization', 'stockpack' ), |
| 422 |
'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' ), |
| 423 |
'options' => array( |
| 424 |
'yes' => __( 'Yes', 'stockpack' ), |
| 425 |
'no' => __( 'No', 'stockpack' ) |
| 426 |
), |
| 427 |
'type' => 'radio', |
| 428 |
'default' => 'no', |
| 429 |
), |
| 430 |
array( |
| 431 |
'name' => 'add_license_state_to_filename', |
| 432 |
'label' => __( 'Update file name with provider name and license state for premium providers', 'stockpack' ), |
| 433 |
'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' ), |
| 434 |
'options' => array( |
| 435 |
'yes' => __( 'Yes', 'stockpack' ), |
| 436 |
'no' => __( 'No', 'stockpack' ) |
| 437 |
), |
| 438 |
'type' => 'radio', |
| 439 |
'default' => 'no', |
| 440 |
), |
| 441 |
), |
| 442 |
'stockpack_debug' => array( |
| 443 |
array( |
| 444 |
'name' => 'download_timeout', |
| 445 |
'label' => __( 'Download timeout in seconds', 'stockpack' ), |
| 446 |
'desc' => __( 'If you have issues downloading the images, increasing this might help', 'stockpack' ), |
| 447 |
'type' => 'number', |
| 448 |
'default' => 30, |
| 449 |
), |
| 450 |
array( |
| 451 |
'name' => 'url_debugging', |
| 452 |
'label' => __( 'Enable URL debugging', 'stockpack' ), |
| 453 |
'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' ), |
| 454 |
'options' => array( |
| 455 |
'yes' => __( 'Yes', 'stockpack' ), |
| 456 |
'no' => __( 'No', 'stockpack' ) |
| 457 |
), |
| 458 |
'type' => 'radio', |
| 459 |
'default' => 'no', |
| 460 |
), |
| 461 |
) |
| 462 |
); |
| 463 |
} |
| 464 |
|
| 465 |
/** |
| 466 |
* Get the value of a settings field |
| 467 |
* |
| 468 |
* @param string $option settings field name |
| 469 |
* @param string $section the section name this field belongs to |
| 470 |
* @param string $default default text if it's not found |
| 471 |
* |
| 472 |
* @return mixed |
| 473 |
*/ |
| 474 |
private function get_option( $option, $section, $default = '' ) { |
| 475 |
|
| 476 |
$options = get_option( $section, array() ); |
| 477 |
|
| 478 |
if ( isset( $options[ $option ] ) ) { |
| 479 |
return $options[ $option ]; |
| 480 |
} |
| 481 |
|
| 482 |
return $default; |
| 483 |
} |
| 484 |
|
| 485 |
/** |
| 486 |
* Set the value of a settings field |
| 487 |
* |
| 488 |
* @param string $option settings field name |
| 489 |
* @param string $section the section name this field belongs to |
| 490 |
* @param string $value |
| 491 |
* |
| 492 |
* @return mixed |
| 493 |
*/ |
| 494 |
private function set_option( $option, $section, $value ) { |
| 495 |
|
| 496 |
$options = get_option( $section, array() ); |
| 497 |
if ( ! is_array( $options ) ) { |
| 498 |
$options = array(); |
| 499 |
} |
| 500 |
|
| 501 |
$options[ $option ] = $value; |
| 502 |
|
| 503 |
update_option( $section, $options ); |
| 504 |
} |
| 505 |
} |
| 506 |
|