PluginProbe
Translation with DeepL API / trunk
Translation with DeepL API vtrunk
trunk 0.1.20180323 1.0 1.2.5.1 1.5.2.5 1.7.5 2.4.3.12 2.4.3.9 2.4.5
wpdeepl / settings / wp-improved-settings.class.php

wp-improved-settings.class.php in Translation with DeepL API trunk, at settings/wp-improved-settings.class.php

646 lines 18.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Improved Settings
4 *
5 * @package wpdeepl_WP_Improved_Settings
6 * @version 20251205
7 *
8 * 20251205 Version 2.0 - Adaptée à l'API v2.0, PCP compliant
9 * 20221115 esc all
10 * 20210111 ajout wpimpsettings_find_option_like
11 * 20200320 ajout des setting en tableau
12 * 20190705 footer actions prise en compte des méthodes
13 * 201991125 plugin_text_domain supprimé
14 * 20191201 plugin paths
15 */
16
17 namespace wpdeepl_WP_Improved_Settings;
18 if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
19
20 if ( !function_exists( 'wpdeepl_WP_Improved_Settings\zebench_get_plugin_paths' ) ) {
21 function zebench_get_plugin_paths() {
22 $array = apply_filters( 'wpdeepl_zebench_get_plugin_paths', array() );
23 return $array;
24 }
25 }
26
27 if( !function_exists('wpdeepl_WP_Improved_Settings\wpimpsettings_find_all_options_like') ){
28 function wpimpsettings_find_all_options_like( $string ) {
29 if ( ! current_user_can( 'manage_options' ) ) {
30 return array();
31 }
32 global $wpdb;
33 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- Prepared statement, admin-only utility function
34 $results = $wpdb->get_results(
35 $wpdb->prepare(
36 "SELECT option_name, option_value FROM $wpdb->options WHERE option_name LIKE %s",
37 '%' . $wpdb->esc_like( $string ) . '%' // Assainissement (esc_like) et wildcards injectés ici
38 )
39 , ARRAY_A );
40
41 return $results;
42 }
43 }
44 if( !function_exists('wpdeepl_WP_Improved_Settings\wpimpsettings_find_option_like') ){
45 function wpimpsettings_find_option_like( $string ) {
46 if ( ! current_user_can( 'manage_options' ) ) {
47 return array();
48 }
49 global $wpdb;
50 $sanitized_string = sanitize_key( $string );
51 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- Prepared statement, admin-only utility function
52 $results = $wpdb->get_results(
53 $wpdb->prepare(
54 "SELECT option_name, option_value FROM $wpdb->options WHERE option_name LIKE %s",
55 $wpdb->esc_like( $sanitized_string ) . '%' // [sanitized_string]%
56 )
57 , ARRAY_A );
58
59 $return = array();
60 if( $results ) {
61 foreach ( $results as $result ) {
62 $name = str_replace( $sanitized_string . '_', '', $result['option_name'] );
63 $explode = explode('_', $name );
64 $value = $result['option_value'];
65 if ( ! empty( $explode[0] ) && ! empty( $explode[1] ) ) {
66 $return[ sanitize_key( $explode[0] ) ][ sanitize_key( $explode[1] ) ] = $value;
67 }
68 }
69 }
70 return $return;
71 }
72 }
73 if ( !class_exists( 'wpdeepl_WP_Improved_Settings\wpdeepl_WP_Improved_Settings' ) ) {
74 class wpdeepl_WP_Improved_Settings {
75 /**
76 * Settings structure from configuration
77 *
78 * @var array
79 */
80 protected $settingsStructure = array();
81
82 /**
83 * Extended actions for maintenance tasks
84 *
85 * @var array
86 */
87 public $extendedActions = array();
88
89 /**
90 * Plugin paths cache
91 *
92 * @var array
93 */
94 protected $plugins_paths = array();
95
96 /**
97 * Settings API instance
98 *
99 * @var WC_Improved_Settings_API
100 */
101 protected $WC_Improved_Settings_API;
102
103 // Configuration properties
104 public $isMainMenu = false;
105 public $plugin_id;
106 public $menu_order = 20;
107 public $minimum_capability = 'manage_options';
108 public $option_page = '';
109 public $defaultSettingsTab = '';
110 public $parent_menu = '';
111 public $post_type = false;
112
113
114 public function __construct() {
115 add_action( 'admin_init', array( $this, 'loadSettings' ) );
116 add_action( 'admin_init', array( $this, 'registerSettings' ) );
117
118 $this->plugins_paths = apply_filters('wpdeepl_zebench_plugins_paths', array() );
119
120 add_action( 'admin_menu', array( $this, 'addToMenu' ), $this->menu_order );
121
122 if ( !class_exists( 'wpdeepl_WP_Improved_Settings\WC_Improved_Settings_API' )) {
123 require_once( dirname( __FILE__ ) . '/wp-improved-settings-api.class.php' );
124 }
125 }
126
127 function getPluginID() {
128 return $this->plugin_id;
129 }
130
131 function getOptionPage() {
132 return $this->option_page;
133 }
134
135 function getMinimumCapability() {
136 return $this->minimum_capability;
137 }
138
139 protected function saveSettings() {
140 // Vérification nonce (sera revérifiée dans l'API)
141 $nonce = isset( $_REQUEST['_wpdeepl_nonce'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['_wpdeepl_nonce'] ) ) : false;
142 if ( ! wp_verify_nonce( $nonce, 'wpdeepl_save_settings' ) ) {
143 wp_die( esc_html__( 'Security check failed', 'wpdeepl' ) );
144 }
145
146 // L'API gère sa propre vérification nonce
147 $this->WC_Improved_Settings_API->process_admin_options();
148 }
149 /*
150 function me() {
151 $this->loadSettings();
152 $this->WC_Improved_Settings_API = WC_Improved_Settings_API( $this->getPluginID(), $this->getSettingsStructure() );
153 return $this->WC_Improved_Settings_API->process_admin_options();
154 }*/
155
156 function maybe_print_notices() {
157 }
158
159 function print_saved_notice() {
160 ?>
161 <div id="message" class="updated notice is-dismissible"><p><strong><?php esc_html_e( 'Settings saved.', 'wpdeepl' ); ?></strong></p></div>
162 <?php
163 }
164
165 public function loadSettings() {
166 $this->settingsStructure = $this->getSettingsStructure();
167 $this->WC_Improved_Settings_API = new \wpdeepl_WP_Improved_Settings\WC_Improved_Settings_API( $this->getPluginID(), $this->settingsStructure );
168 // load settings into $this sttings ?
169 //wpdeepl_debug_display( $this->settingsStructure ); die( 'oka6z4e4z64ze4' );
170 }
171
172 /**
173 * Add Settings link to menu
174 *
175 * @access public
176 * @return voidaddToMenu
177 */
178 public function addToMenu() {
179 //die( 'menu to '.$this->parent_menu . ' page title = ' . $this->getPageTitle() .' menu = ' . $this->getMenuTitle() . ' cap ' . 'manage_options' . ' option page = ' . $this->getOptionPage() );
180 add_submenu_page(
181 $this->parent_menu,
182 $this->getPageTitle(),
183 $this->getMenuTitle(),
184 $this->getMinimumCapability(),
185 $this->getOptionPage(),
186 array( $this, 'settingsPage' )
187 );
188 }
189
190 /**
191 * Print settings page
192 *
193 * @access public
194 * @return void
195 */
196 public function settingsPage() {
197 // Get current tab
198 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- navigation tab, no data processing
199 $current_tab = ( isset( $_GET['tab'] ) ) ? sanitize_key( wp_unslash( $_GET['tab'] ) ) : $this->defaultSettingsTab;
200
201 // Print header
202 $this->printHeader();
203
204 $this->printFields();
205
206 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- extendedActions is not defined by user input.
207 if ( count( $this->extendedActions ) ) foreach ( $this->extendedActions as $action => $function ) {
208 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- The action name is from the class definitions, not user input.
209 if ( isset( $_REQUEST[$action] ) ) {
210 if ( function_exists( $function) ) {
211 $function();
212 }
213 else {
214 /* translators: function does not exist */
215 printf( esc_html__( 'Undefined function: %s', 'wpdeepl' ), esc_html( $function ) );
216 }
217 }
218 }
219 $this->printFooter();
220 }
221
222 public function registerSettings() {
223 // Check if current user can manage plugin settings
224 if ( !is_admin() ) {
225 return;
226 }
227
228 $key_value = false;
229 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- plugin_id is hardcoded.
230 if( isset( $_REQUEST[$this->plugin_id . '_options_save'] ) ) {
231 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- plugin_id is hardcoded.
232 $key_value = sanitize_text_field( wp_unslash( $_REQUEST[$this->plugin_id . '_options_save'] ) );
233 }
234 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verified in saveSettings()
235 if ( isset( $_REQUEST['save'] ) && $key_value ) {
236 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verified in saveSettings()
237 $this->saveSettings();
238 if ( method_exists( $this, 'on_save' ) ) {
239 $this->on_save();
240 }
241
242 add_action( 'admin_notices', array( $this, 'print_saved_notice' ) );
243 }
244 add_action( 'admin_notices', array( $this, 'maybe_print_notices' ) );
245
246 // Iterate over tabs
247 foreach ( $this->settingsStructure as $tab_key => $tab ) {
248 // Register tab
249 register_setting(
250 $this->option_page .'_group_' . $tab_key,
251 $this->option_page,
252 array(
253 'type' => 'array',
254 'sanitize_callback' => array( $this, 'sanitizeSettings' ),
255 )
256 );
257
258 // Iterate over sections
259 foreach ( $tab['sections'] as $section_key => $section ) {
260 $settings_page_id = $this->plugin_id . '-admin-' . str_replace( '_', '-', $tab_key );
261
262 // Register section
263 add_settings_section(
264 $section_key,
265 $section['title'],
266 array( $this, 'print_section_info' ),
267 $settings_page_id
268 );
269
270 // Iterate over fields
271 if( isset( $section['fields'] ) ) foreach ( $section['fields'] as $field_key => $field ) {
272 // Register field
273 add_settings_field(
274 $this->plugin_id . '_' . $field_key,
275 $field['title'],
276 array( $this, 'print_field_' . $field['type'] ),
277 $settings_page_id,
278 $section_key,
279 array(
280 'field_key' => $field_key,
281 'field' => $field,
282 'data-' . $this->plugin_id . '-setting-hint' => !empty( $field['hint'] ) ? $field['hint'] : null,
283 )
284 );
285 }
286 }
287 }
288 }
289
290 /**
291 * Sanitize settings before saving
292 *
293 * @param mixed $input The input value to sanitize.
294 * @return mixed Sanitized value.
295 */
296 public function sanitizeSettings( $input ) {
297 if ( ! is_array( $input ) ) {
298 return sanitize_text_field( $input );
299 }
300
301 $sanitized = array();
302 foreach ( $input as $key => $value ) {
303 $sanitized_key = sanitize_key( $key );
304 if ( is_array( $value ) ) {
305 $sanitized[ $sanitized_key ] = $this->sanitizeSettings( $value );
306 } else {
307 $sanitized[ $sanitized_key ] = sanitize_text_field( $value );
308 }
309 }
310 return $sanitized;
311 }
312
313 protected function getActiveTab() {
314 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verified in saveSettings()
315 if ( isset( $_GET[ 'tab' ] ) ) {
316 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- navigation tab, sanitized, no data processing
317 $active_tab = sanitize_key( wp_unslash( $_GET[ 'tab' ] ) );
318 }
319 elseif ( $this->defaultSettingsTab != '' ) {
320 $active_tab = $this->defaultSettingsTab;
321 }
322
323 if ( !isset( $this->settingsStructure[$active_tab] ) ) {
324 return false;
325 }
326 return $active_tab;
327 }
328
329 function printHeader() {
330 $tabs = array();
331 foreach ( $this->settingsStructure as $setting_tab_slug => $setting_data ) {
332 $tabs[$setting_tab_slug] = $setting_data['title'];
333 }
334 //echo '<div class="wrap woocommerce"><form method="post" action="options.php" enctype="multipart/form-data">';
335 ?>
336
337 <div class="wrap">
338
339 <div id="icon-themes" class="icon32"></div>
340 <h2><?php echo esc_html( $this->getPageTitle() ); ?></h2>
341 <?php
342 settings_errors();
343
344 $active_tab = $this->getActiveTab();
345
346 $parent_menu = $this->parent_menu;
347 $parsed_url = wp_parse_url( $parent_menu );
348 $extended_url = '';
349 if ( isset( $parsed_url['query'] ) && strlen( $parsed_url['query'] ) ) {
350 $extended_url = '&' . $parsed_url['query'];
351 }
352
353 if ( property_exists($this, 'post_type' ) && $this->post_type ) {
354 $action = 'edit.php';
355 }
356 else {
357 $action = 'admin.php';
358 }
359 $action .= '?';
360
361 if ( $this->post_type ) {
362 $action .= 'post_type=' . $this->post_type .'&';
363 }
364 $action .= 'page=' . $this->getOptionPage();
365 if ($active_tab) {
366 $action .= '&tab=' . $active_tab;
367 }
368
369 $page_link = '?';
370 if ( $this->post_type ) {
371 $page_link .= 'post_type=' . $this->post_type .'&';
372 }
373 $page_link .= 'page=' . $this->getOptionPage();
374
375
376
377 ?>
378 <form method="post" id="mainform" action="<?php echo esc_attr( $action ); ?>" enctype="multipart/form-data">
379 <input type="hidden" name="<?php echo esc_attr( $this->plugin_id ); ?>_options_save" value="1">
380 <input type="hidden" name="tab" value="<?php echo esc_attr( $active_tab ); ?>">
381
382 <nav class="nav-tab-wrapper woo-nav-tab-wrapper">
383 <?php foreach ( $tabs as $tab => $label ) :
384 $nav_tab_id = $this->getOptionPage() . '-' . $tab; ?>
385 <a id="<?php echo esc_attr( $nav_tab_id ); ?>" href="<?php echo esc_url( $page_link ) . '&tab=' . esc_attr( $tab . $extended_url ); ?>" class="nav-tab <?php echo $active_tab == $tab ? 'nav-tab-active' : ''; ?>"><?php echo esc_html( $label ); ?></a>
386 <?php endforeach; ?>
387 </nav>
388
389 <?php
390 if ( !$active_tab = $this->getActiveTab() ) {
391 return false;
392 }
393
394 /*
395 $tab_data = $this->settingsStructure[$active_tab];
396 $defaults = array(
397 'title' => '',
398 'class' => '',
399 'description' => '',
400 'sections' => array(),
401 );
402 $tab_data = wp_parse_args( $tab_data, $defaults );
403
404 $this->displayTabTitle( $active_tab, $tab_data );
405 */
406 }
407
408 function printFields() {
409 if (!$this->getActiveTab()) {
410 return false;
411 }
412 $active_tab = $this->getActiveTab();
413 $tab_data = $this->settingsStructure[$active_tab];
414
415
416 //wpdeepl_debug_display($tab_data, " T AB DATA");
417
418
419 foreach ( $tab_data['sections'] as $section_id => $section ) {
420 $defaults = array(
421 'title' => '',
422 'class' => '',
423 'description' => '',
424 'fields' => array(),
425 'html' => false,
426 );
427 $section_data = wp_parse_args( $section, $defaults );
428
429 //wpdeepl_debug_display( $section );
430 ?>
431 <h3 class="wc-settings-sub-title <?php echo esc_attr( $section_data['class'] ); ?>" id="<?php echo esc_attr( $section_id ); ?>"><?php echo wp_kses_post( $section_data['title'] ); ?></h3>
432 <?php if ( ! empty( $section_data['description'] ) ) : ?>
433 <p><?php echo wp_kses_post( $section_data['description'] ); ?></p>
434 <?php endif; ?>
435
436 <table class="form-table">
437
438 <?php
439
440 $this->WC_Improved_Settings_API->id = $active_tab;
441
442 $section_fields = $section_data['fields'];
443
444 $fields = array();
445 foreach ( $section_fields as $field ) {
446 $fields[] = $field;
447 }
448
449 //wpdeepl_debug_display($fields, "on a fields");
450
451 $this->WC_Improved_Settings_API->generate_settings_html( $fields );
452 ?>
453 </table>
454 <?php
455 if ( isset( $section['html'] ) && $section['html'] ) {
456 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- HTML already escaped, we need to ouput raw HTML
457 //echo ( $section['html'] );
458 echo wp_kses_post( $section['html'] );
459 }
460 ?>
461
462 <?php if ( isset( $section['actions'] ) && $section['actions'] ) foreach ( $section['actions'] as $action ) {
463 $param = false;
464 if ( is_array( $action ) ) {
465 list($action, $param) = $action;
466 if ( function_exists( $action ) ) {
467 $action( $param );
468 }
469 }
470 elseif ( function_exists( $action ) ) {
471 $action( $param );
472 }
473
474 else {
475 /* translators: name of the function not found */
476 printf( esc_html__( 'Undefined function: %s', 'wpdeepl' ), esc_html( $action ) );
477 }
478 }
479
480 ?>
481
482
483 <?php if ( count( $fields ) ) : ?>
484
485 <p class="submit">
486 <?php wp_nonce_field('wpdeepl_save_settings', '_wpdeepl_nonce' ); ?>
487 <?php if ( empty( $GLOBALS['hide_save_button'] ) ) : ?>
488 <button name="save" class="button-primary" type="submit" value="<?php esc_attr_e( 'Update', 'wpdeepl' ); ?>"><?php esc_html_e( 'Update', 'wpdeepl' ); ?></button>
489 <?php endif; ?>
490 </p>
491 <?php endif; ?>
492
493 <?php
494 }
495 ?>
496
497 <?php
498 }
499
500 function displayTabTitle( $tab_id, $tab_data ) {
501 ?>
502 <h2 class="wc-settings-sub-title <?php echo esc_attr( $tab_data['class'] ); ?>" id="<?php echo esc_attr( $tab_id ); ?>"><?php echo wp_kses_post( $tab_data['title'] ); ?></h2>
503 <?php if ( ! empty( $tab_data['description'] ) ) : ?>
504 <p><?php echo wp_kses_post( $tab_data['description'] ); ?></p>
505 <?php endif;
506 }
507
508 protected function tabFooter( $tab_id, $tab_data ) {
509 if ( isset( $tab_data['footer'] ) ) {
510 if ( isset( $tab_data['footer']['html'] ) ) foreach ( $tab_data['footer']['html'] as $raw_html ) {
511 // HTML déjà échappé dans la configuration
512 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
513 echo $raw_html;
514 }
515 if ( isset( $tab_data['footer']['actions'] ) ) {
516 echo '<hr />';
517 foreach ( $tab_data['footer']['actions'] as $action ) {
518 $param = false;
519
520 if ( is_array( $action ) ) {
521 list($object, $method) = $action;
522 if ( method_exists( $object, $method ) ) {
523 $object->$method();
524 }
525 }
526 elseif ( function_exists( $action ) ) {
527 $action( $param );
528 }
529 else {
530 /* translators: name of the function not found */
531 printf( esc_html__( 'Undefined function: %s', 'wpdeepl' ), esc_html( $action ) );
532 }
533 }
534 }
535 }
536 }
537
538 function printFooter() {
539 ?>
540 <?php
541 $active_tab = $this->getActiveTab();
542 if ( $active_tab ) {
543 $tab_data = $this->settingsStructure[$active_tab];
544 $this->tabFooter( $active_tab, $tab_data );
545 }
546 ?>
547
548 </form>
549
550 </div>
551 <?php
552 }
553
554
555 public function showServerInfo() {
556 echo '<h2>' . esc_html__('Server information', 'wpdeepl' ) . '</h2>';
557
558 if( function_exists('ini_get_all' ) ) {
559
560 $ini_values = ini_get_all();
561 $timeout = $ini_values['max_execution_time']['local_value'];
562 }
563 else {
564 $timeout = '';
565 }
566
567 $bytes = memory_get_usage();
568 $s = array('o', 'Ko', 'Mo', 'Go', 'To', 'Po');
569 $e = floor(log($bytes)/log(1024));
570 $memory_usage = sprintf('%.2f '.$s[$e], ($bytes/pow(1024, floor($e))));
571
572
573
574 if ($timeout > 1000 ) {
575 $timeout = round($timeout /1000,1);
576 }
577
578 $informations = array(
579 'Server time' => gmdate('d/m/Y H:i:s'),
580 'Real path' => get_home_path(),
581 'PHP version' => phpversion(),
582 'Timeout' => $timeout .' s',
583 'Memory usage' => $memory_usage,
584 );
585
586 if ( function_exists( 'sys_getloadavg') ) {
587 $sys_getloadavg = sys_getloadavg();
588 if( is_array( $sys_getloadavg ) ){
589 $informations['Load'] = implode(', ', $sys_getloadavg );
590 }
591 else {
592 $informations['Load'] = $sys_getloadavg;
593 }
594 }
595
596 foreach ($informations as $label => $value) {
597 printf( "<p><strong>%s</strong>&nbsp;%s</p>", esc_html( $label ), esc_html( $value ) );
598 }
599
600
601 }
602
603
604
605 public function showLogs() {
606
607 if ( !is_admin() ) {
608 return false;
609 }
610 $path = $this->log_folder;
611
612 $logs = glob( trailingslashit( $path ) . '*.log');
613 //wpdeepl_debug_display($logs, "LOGS");
614 if ($logs) foreach ($logs as $log_file) {
615 $file_name = basename( $log_file );
616 $contents = file_get_contents( $log_file );
617 if (preg_match('#(\d+)-(\d+)-(\w+)\.log#', $file_name, $match)) {
618 $date = $match[2] . '/' . $match[1];
619 echo '<h3>';
620 printf(
621 /* translators: 1. file name 2. month */
622 esc_html__("File '%1\$s' for %2\$s", 'wpdeepl' ),
623 esc_html( $match[3] ),
624 esc_html( $date )
625 );
626 echo '</h3>';
627 $lines = explode( "\n", $contents);
628 foreach ( $lines as $line ) {
629 //$line = preg_replace('#\{"body":".*?"},#ism', '-body-', $line);
630 //$line = preg_replace( '#"raw":".*?","headers#ism', 'headers', $line );
631 $line = preg_replace( '#"body":"<!DOCTYPE.*?","headers#ism', '"body":"PROBLEME COTE INSURED (disponible dans les logs complets)", "headers', $line);
632 if ( stripos( $line, '<!DOCTYPE html>' ) ) {
633 continue;
634 }
635 // Contenu log potentiellement dangereux - échapper
636 echo "<br /><br />" . esc_html( $line ) . "\n";
637 }
638 //wpdeepl_debug_display($contents);
639
640 }
641 }
642
643 }
644 }
645 }
646