PluginProbe
پارسی دیت – Parsi Date / 6.3
پارسی دیت – Parsi Date v6.3
6.3 6.2.1 6.2 6.1 5.1.6 5.1.7 5.1.8 5.1.8.2 6.0 trunk 1.0 1.1 1.2 1.3 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 2.0.0-alpha 2.1 2.1.1 2.1.2 2.1.3 2.1.5 All 49 releases
wp-parsidate / inc / Admin / AdminSettings.php
AdminSettings.php
580 lines 21.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace WPParsidate\Admin;
4
5 defined( 'ABSPATH' ) || exit;
6
7 use WPParsidate\Helper\{Cache, HTML, Notice, Param, Sanitizing, Validating};
8 use WPParsidate\Settings\Settings;
9
10 class AdminSettings {
11 private static $settings = [];
12
13 public function __construct() {
14 add_action( 'wp_parsidate_submit_settings_form', [ $this, 'saveForm' ], 0 );
15 }
16
17 public function saveForm( $tab ): void {
18 $settings = self::getSettings( $tab );
19
20 if ( $settings ) {
21 $options = [];
22 $saveFields = HTML::saveFields;
23 $currentSection = null;
24 $optionsName = $settings['settings_key'] ?? null;
25
26 if ( self::isSectionMode( $settings ) ) {
27 $currentSection = self::getActiveSection( $settings );
28 $tabSettings = $settings['sections'][ $currentSection ]['settings'];
29 $optionsName = $settings['sections'][ $currentSection ]['settings_key'] ?? $optionsName;
30 } else {
31 $tabSettings = $settings['settings'];
32 }
33
34 if ( is_array( $tabSettings ) ) {
35 $tabSettings = self::saveRepeatableSettings( $tabSettings, $optionsName );
36
37 foreach ( $tabSettings as $setting ) {
38 $setting['type'] = strtolower( $setting['type'] );
39
40 if ( ( isset( $setting['save'] ) && $setting['save'] === false ) ||
41 ( isset( $setting['is_repeatable'] ) && $setting['is_repeatable'] ) ||
42 ! in_array( $setting['type'], $saveFields, true ) ) {
43 continue;
44 }
45
46 $default = self::getSettingDefault( $setting );
47 if ( in_array( $setting['type'], [ 'checkbox', 'toggle' ] ) ) {
48 // PHPCS ignore reason: Nonce check is already happening before this logic in `AdminPages` class.
49 // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing
50 $value = isset( $_POST[ WP_PARSI_INPUT_PREFIX . $setting['id'] ] ) ? Param::post( WP_PARSI_INPUT_PREFIX . $setting['id'], $default ) : false;
51 } else {
52 $value = Param::post( WP_PARSI_INPUT_PREFIX . $setting['id'], $default );
53 }
54
55 $value = self::sanitizeSetting( $value, $setting );
56
57 if ( is_array( $value ) ) {
58 $value = self::sanitizeOptionsSetting( $value, $setting );
59 }
60
61 if ( $setting['type'] === 'colorpalette' ) {
62 $value = array_values( $value );
63 }
64
65 $value = apply_filters( 'wp_parsidate_setting_value_before_save', $value, $setting );
66
67 $options[ $setting['id'] ] = $value;
68 }
69 }
70
71 $options = apply_filters( 'wp_parsidate_settings_before_save', $options, $tab );
72 if ( count( $options ) ) {
73 $saved = Settings::saves( $options, $optionsName );
74
75 if ( $saved ) {
76 Cache::set( 'settings_saved', true );
77 Notice::add( $tab, apply_filters( 'wp_parsidate_save_settings_success_message', esc_html__( 'Settings saved.', 'wp-parsidate' ), $tab ), 'success' );
78 do_action( 'wp_parsidate_save_settings_success', $tab, $currentSection, $options );
79 } else {
80 Notice::add( $tab, apply_filters( 'wp_parsidate_save_settings_error_message', esc_html__( 'Error saving settings!', 'wp-parsidate' ), $tab ), 'error' );
81 }
82 }
83 }
84 }
85
86 private static function saveRepeatableSettings( $settings, $optionsName ) {
87 $types = array_column( $settings, 'type' );
88 $types = array_map( 'strtolower', $types );
89
90 if ( in_array( 'startrepeatableelements', $types, true ) ) {
91 $saveValue = [];
92 $saveRepeatableElements = $repeatableSettingId = false;
93 $maxRepeatElements = $maxRepeat = 100;
94
95 foreach ( $settings as $key => $setting ) {
96 $setting['type'] = strtolower( $setting['type'] );
97
98 if ( $setting['type'] === 'startrepeatable' ) {
99 $maxRepeatElements = (int) ( $setting['max_repeat'] ?? $maxRepeat );
100 }
101
102 if ( $setting['type'] === 'startrepeatableelements' ) {
103 $saveRepeatableElements = true;
104 $repeatableSettingId = $setting['id'];
105 $saveValue[ $repeatableSettingId ] = [];
106 }
107
108 if ( $saveRepeatableElements && ! in_array( $setting['type'], [
109 'startrepeatableelements',
110 'endrepeatableelements'
111 ] ) ) {
112 $setting['is_repeatable'] = true;
113 $default = self::getSettingDefault( $setting );
114 $rowKey = str_replace( WP_PARSI_INPUT_PREFIX . $repeatableSettingId . '_', '', WP_PARSI_INPUT_PREFIX . $setting['id'] );
115 $value = Param::post( WP_PARSI_INPUT_PREFIX . $setting['id'], $default );
116
117 if ( is_array( $value ) ) {
118 $count = count( $value );
119 for ( $i = 0; $i < $count; $i ++ ) {
120 $saveValue[ $repeatableSettingId ][ $i ][ $rowKey ] = $value[ $i ];
121 }
122
123 $saveValue[ $repeatableSettingId ] = array_slice( $saveValue[ $repeatableSettingId ], 0,
124 $maxRepeatElements );
125 }
126 }
127
128 if ( $setting['type'] === 'endrepeatableelements' ) {
129 $saveRepeatableElements = false;
130 }
131
132 $settings[ $key ] = $setting;
133 }
134
135 if ( ! empty( $saveValue ) ) {
136 foreach ( $saveValue as $settingKey => $settingValue ) {
137 foreach ( $settingValue as $index => $value ) {
138 $value = array_map( 'trim', $value );
139 if ( implode( $value ) === '' ) {
140 unset( $settingValue[ $index ] );
141 }
142 }
143 $saveValue[ $settingKey ] = array_values( $settingValue );
144 }
145
146 Settings::saves( $saveValue, $optionsName );
147 }
148 }
149
150 return $settings;
151 }
152
153 public static function getSettingDefault( $setting ) {
154 $default = ! empty( $setting['default'] ) ? $setting['default'] : null;
155
156 // Set default value for toggle, checkbox, addon
157 if ( empty( $setting['default'] ) && in_array( $setting['type'], [ 'toggle', 'checkbox', 'addon', 'tinyaddon' ], true ) ) {
158 $default = 0;
159 }
160
161 /*if ( empty( $setting['default'] ) && in_array( $setting['type'], [ 'addon', 'tinyaddon' ], true ) ) {
162 $default = false;
163 }*/
164
165 // Set default value for imageSizeSelect
166 if ( empty( $setting['default'] ) && $setting['type'] === 'imagesizeselect' ) {
167 $default = 'thumbnail';
168 }
169
170 // Set default value for elements with multiple attr: select, termSelect, postSelect, imageSizeSelect
171 if ( isset( $data['multiple'] ) && $data['multiple'] && empty( $setting['default'] ) && in_array( $setting['type'],
172 [
173 'select',
174 'termselect',
175 'menuselect',
176 'postselect',
177 'imagesizeselect',
178 'orderstatusselect',
179 'currencyselect',
180 ] ) ) {
181 $default = [];
182 }
183
184 return $default;
185 }
186
187 public static function sanitizeOptionsSetting( $value, $setting ) {
188 if ( ! is_array( $value ) ) {
189 return $value;
190 }
191
192 if ( empty( $setting['sanitize_options'] ) ) {
193 if ( ( isset( $setting['multiple'] ) && $setting['multiple'] ) ) {
194 if ( in_array( $setting['type'], [
195 'termselect',
196 'menuselect',
197 'postselect',
198 'userselect'
199 ] ) ) {
200 $setting['sanitize_options'] = 'int';
201 }
202
203 if ( in_array( $setting['type'], [ 'orderstatusselect', 'currencyselect' ] ) ) {
204 $setting['sanitize_options'] = 'text';
205 }
206 }
207
208 if ( $setting['type'] === 'colorpalette' ) {
209 $setting['sanitize_options'] = 'color';
210 }
211 }
212
213 if ( isset( $setting['sanitize_options'] ) && method_exists( Sanitizing::class,
214 $setting['sanitize_options'] ) ) {
215 $value = array_map( 'WPParsidate\Helper\Sanitizing::' . $setting['sanitize_options'], $value );
216 }
217
218 return $value;
219 }
220
221 public static function sanitizeSetting( $value, $setting ) {
222 if ( empty( $setting['sanitize'] ) ) {
223 if ( in_array( $setting['type'], [ 'checkboxinline', 'colorpalette' ] ) ||
224 ( isset( $setting['multiple'] ) && $setting['multiple'] &&
225 in_array( $setting['type'], [
226 'taxonomyselect',
227 'termselect',
228 'menuselect',
229 'posttypeselect',
230 'postselect',
231 'imagesizeselect',
232 'userroleselect',
233 'userselect',
234 'orderstatusselect',
235 'currencyselect',
236 'select'
237 ] ) ) ) {
238 $setting['sanitize'] = 'array';
239
240 } elseif ( in_array( $setting['type'], [
241 'text',
242 'search',
243 'password',
244 'tel',
245 'hidden',
246 'radio',
247 'radioinline',
248 'select',
249 'posttypeselect',
250 'taxonomyselect',
251 'imagesizeselect',
252 'orderstatusselect',
253 'currencyselect',
254 'userroleselect',
255 'media'
256 ], true ) ) {
257 $setting['sanitize'] = 'text';
258
259 } elseif ( $setting['type'] === 'number' ) {
260 $setting['sanitize'] = 'float';
261
262 } elseif ( $setting['type'] === 'email' ) {
263 $setting['sanitize'] = 'email';
264
265 } elseif ( $setting['type'] === 'url' ) {
266 $setting['sanitize'] = 'url';
267
268 } elseif ( $setting['type'] === 'textarea' ) {
269 $setting['sanitize'] = 'textarea';
270
271 } elseif ( in_array( $setting['type'], [ 'color', 'wpcolorpicker' ] ) ) {
272 $setting['sanitize'] = 'color';
273
274 } elseif ( $setting['type'] === 'range' ) {
275 $setting['sanitize'] = 'int';
276
277 } elseif ( in_array( $setting['type'], [ 'postselect', 'termselect', 'menuselect', 'userselect' ] ) ) {
278 $setting['sanitize'] = 'absint';
279
280 } elseif ( in_array( $setting['type'], [ 'addon', 'tinyaddon' ] ) ) {
281 $setting['sanitize'] = 'bool';
282
283 } elseif ( $setting['type'] === 'gradientcolorpicker' ) {
284 $setting['sanitize'] = 'jsonArray';
285 }
286 }
287
288 if ( ! empty( $setting['sanitize'] ) && method_exists( Sanitizing::class, $setting['sanitize'] ) ) {
289 $value = Sanitizing::{$setting['sanitize']}( $value );
290 $value = wp_slash( $value );
291 }
292
293 return $value;
294 }
295
296 public static function getSettings( $tab ) {
297 if ( ! isset( self::$settings[ $tab ] ) ) {
298 self::$settings[ $tab ] = apply_filters( 'wp_parsidate_' . $tab . '_settings', [] );
299 }
300
301 return self::$settings[ $tab ];
302 }
303
304 public static function allSettings( $tab = null ) {
305 $settings = apply_filters( 'wp_parsidate_settings', [] );
306
307 if ( ! is_null( $tab ) ) {
308 return ! empty( $settings[ $tab ] ) ? $settings[ $tab ] : false;
309 }
310
311 return $settings;
312 }
313
314 public static function printPage( $currentTab, $settings ): void {
315 $optionsName = $settings['settings_key'] ?? null;
316
317 echo '<form method="post" id="wppd-settings-form">';
318 wp_nonce_field( 'settings_submit_' . $currentTab, '_form_nonce' );
319 if ( self::isSectionMode( $settings ) ) {
320 $currentSection = self::getActiveSection( $settings );
321 $currentSettings = $settings['sections'][ $currentSection ]['settings'] ?? [];
322 $optionsName = $settings['sections'][ $currentSection ]['settings_key'] ?? $optionsName;
323
324 do_action( 'wp_parsidate_section_content', $currentTab, $currentSection, $currentSettings );
325 self::printSettings( $currentSettings, $optionsName );
326 } else {
327 $currentSettings = $settings['settings'] ?? [];
328 self::printSettings( $currentSettings, $optionsName );
329 }
330 echo '</form>';
331 }
332
333 private static function printSettings( $settings, $optionsName ): void {
334 if ( is_array( $settings ) ) {
335 $settings = self::checkRepeatableSettings( $settings, $optionsName );
336 foreach ( $settings as $key => $field ) {
337 if ( ! empty( $field['type'] ) && method_exists( HTML::class, strtolower( $field['type'] ) ) ) {
338 $field['default'] = $field['default'] ?? null;
339
340 if ( isset( $field['force_value'] ) ) {
341 $field['setting_value'] = $field['force_value'];
342 } elseif ( isset( $field['id'] ) ) {
343 $field['setting_value'] = Settings::get( $field['id'], $field['default'], $optionsName );
344 }
345
346 $field['type'] = strtolower( $field['type'] );
347
348 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
349 echo HTML::{$field['type']}( $field );
350 }
351 }
352 }
353 }
354
355 private static function checkRepeatableSettings( $settings, $optionsName ): array {
356 $types = array_column( $settings, 'type' );
357 $types = array_map( 'strtolower', $types );
358
359 if ( in_array( 'startrepeatableelements', $types, true ) ) {
360 $repeatableElementsCount = ( array_count_values( $types ) )['startrepeatableelements'];
361 $repeatableElementsProcessedIDs = [];
362 $maxRepeatElements = $maxRepeat = 100;
363
364 for ( $repeatableElementsCountNumber = 0; $repeatableElementsCountNumber < $repeatableElementsCount; $repeatableElementsCountNumber ++ ) {
365 $repeatableElements = [];
366 $saveRepeatableElements = $repeatableSettingValue = $repeatableSettingId = false;
367 $repeatableElementsIndex = 0;
368 $index = - 1;
369
370 foreach ( $settings as $key => $setting ) {
371 $setting['type'] = strtolower( $setting['type'] );
372 $index ++;
373
374 if ( $setting['type'] === 'startrepeatable' ) {
375 $maxRepeatElements = (int) ( $setting['max_repeat'] ?? $maxRepeat );
376 }
377
378 if ( $setting['type'] === 'startrepeatableelements' ) {
379 $saveRepeatableElements = true;
380 $repeatableElementsIndex = $index;
381 $repeatableSettingId = $setting['id'];
382 $repeatableSettingValue = Settings::get( $repeatableSettingId, [], $optionsName );
383 }
384
385 if ( $saveRepeatableElements && in_array( $repeatableSettingId, $repeatableElementsProcessedIDs, true ) ) {
386 $saveRepeatableElements = false;
387 continue;
388 }
389
390 if ( $saveRepeatableElements ) {
391 if ( ! in_array( $setting['type'], [ 'startrepeatableelements', 'endrepeatableelements' ] ) ) {
392 $setting['is_repeatable'] = true;
393 }
394
395 $repeatableElements[ $key ] = $setting;
396 }
397
398 $settings[ $key ] = $setting;
399
400 if ( $saveRepeatableElements && $setting['type'] === 'endrepeatableelements' ) {
401 $saveRepeatableElements = false;
402 $addElements = [];
403 $repeatableElementsProcessedIDs[] = $repeatableSettingId;
404
405 if ( is_array( $repeatableSettingValue ) && count( $repeatableSettingValue ) ) {
406 foreach ( $repeatableSettingValue as $rowIndex => $rowValue ) {
407 foreach ( $repeatableElements as $repeatableElementIndex => $repeatableElement ) {
408 if ( ! in_array( $repeatableElement['type'], [
409 'startrepeatableelements',
410 'endrepeatableelements'
411 ] ) ) {
412 $repeatableRowKey = str_replace( $repeatableSettingId . '_', '', $repeatableElementIndex );
413
414 if ( isset( $rowValue[ $repeatableRowKey ] ) ) {
415 $repeatableElement['force_value'] = $rowValue[ $repeatableRowKey ];
416 }
417 }
418
419 $addElements[ $repeatableElementIndex . '_' . $rowIndex ] = $repeatableElement;
420 }
421 }
422 }
423
424 if ( ! empty( $addElements ) ) {
425 $addElements = array_slice( $addElements, 0, $maxRepeatElements * count( $repeatableElements ) );
426 //$settings = Helper::arrayInsertAfter( $settings, $repeatableElementsIndex, $addElements );
427
428 if ( count( $addElements ) / count( $repeatableElements ) >= $maxRepeatElements ) {
429 array_splice( $settings, $repeatableElementsIndex, count( $repeatableElements ), $addElements );
430 } else {
431 array_splice( $settings, $repeatableElementsIndex, 0, $addElements );
432 }
433 }
434
435 break;
436 }
437 }
438 }
439 }
440
441 return $settings;
442 }
443
444 public static function headerSettings( $currentTab, $settings ): void {
445 if ( empty( $settings['title'] ) ) {
446 return;
447 }
448
449 $currentSection = self::getActiveSection( $settings );
450 $headerImage = apply_filters( 'wp_parsidate_settings_header_image', $settings['header_image'] ?? '',
451 $currentTab, $currentSection, $settings );
452 $headerImage = ! empty( $headerImage ) && Validating::isUrl( $headerImage ) ? $headerImage : false;
453
454 echo '<header id="wppd-settings-header" class="wppd-header ' . ( $headerImage ? 'wppd-has-header-image' : '' ) . '">';
455 echo '<div class="wppd-header-title" style="' . ( $headerImage ? 'background-image: url(' . esc_url_raw( $headerImage ) . ');' : '' ) . '">';
456 echo '<h1 class="wppd-header-tab-title">' . esc_html( $settings['title'] ) . '</h1>';
457 if ( ! empty( $settings['desc'] ) ) {
458 echo '<p class="wppd-description">' . $settings['desc'] . '</p>';
459 }
460 echo '</div>';
461 if ( ! $currentSection ) {
462 echo '<hr class="wppd-header-separator"/>';
463 }
464 echo '<div class="wppd-header-links">';
465 self::printSections( $currentTab, $settings );
466 echo '</div>';
467 echo '</header>';
468
469 if ( apply_filters( 'wp_parsidate_' . $currentTab . '_tab_content_display_notice', false ) ) {
470 Notice::display( '*' );
471 Notice::display( $currentTab );
472 }
473 }
474
475 public static function footerSettings( $currentTab, $currentSection ): void {
476 if ( ! apply_filters( 'wp_parsidate_settings_display_footer', true, $currentTab,
477 $currentSection ) || ! apply_filters( 'wp_parsidate_' . $currentTab . '_settings_display_footer', true,
478 $currentSection ) ) {
479 return;
480 }
481
482 echo '<footer id="wppd-settings-footer" class="wppd-footer wppd-settings-footer">';
483
484 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
485 echo HTML::button( [
486 'id' => 'settings-submit',
487 'title' => esc_html( apply_filters( 'wp_parsidate_settings_submit_button_title',
488 esc_html__( 'Save changes', 'wp-parsidate' ), $currentTab ) ),
489 'button_type' => 'submit',
490 'class' => 'wppd-button-primary',
491 'attributes' => [
492 'form' => 'wppd-settings-form'
493 ]
494 ] );
495
496 if ( apply_filters( 'wp_parsidate_' . $currentTab . '_settings_display_reset_button', true ) ) {
497 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
498 echo HTML::button( [
499 'id' => 'settings-reset',
500 'title' => esc_html( apply_filters( 'wp_parsidate_settings_reset_button_title',
501 esc_html__( 'Discard changes', 'wp-parsidate' ), $currentTab ) ),
502 'button_type' => 'reset',
503 'attributes' => [
504 'form' => 'wppd-settings-form'
505 ]
506 ] );
507 }
508 echo '</footer>';
509 }
510
511 private static function printSections( $currentTab, $settings ): void {
512 if ( self::isSectionMode( $settings ) ) {
513 $currentSection = self::getActiveSection( $settings );
514 $sections = self::getSections( $settings['sections'] );
515
516 if ( empty( $sections ) ) {
517 return;
518 }
519
520 echo '<div class="wppd-section-links"><ul>';
521 foreach ( $sections as $key => $section ) {
522 echo '<li>';
523 echo '<a href="' . esc_url_raw( AdminPages::link( [
524 'tab' => $currentTab,
525 'section' => $key
526 ] ) ) . '" title="' . esc_html( $section['desc'] ) . '" class="wppd-section-link' . ( $key === $currentSection ? ' wppd-section-link-current' : '' ) . '">' . esc_html( $section['title'] ) . '</a>';
527 echo '</li>';
528 }
529 echo '</ul>';
530
531 if ( ! empty( $sections[ $currentSection ]['desc'] ) && apply_filters( 'wp_parsidate_display_section_description',
532 false, $currentTab, $currentSection ) ) {
533 echo '<p class="wppd-description">' . esc_html( $sections[ $currentSection ]['desc'] ) . '</p>';
534 }
535
536 echo '</div>';
537 }
538 }
539
540 private static function getSections( $sections ): array {
541 $sections = array_map( static function ( $section ) {
542 if ( empty( $section['title'] ) ) {
543 return '';
544 }
545
546 return [ 'title' => $section['title'], 'desc' => empty( $section['desc'] ) ? '' : $section['desc'] ];
547 }, $sections );
548
549 return array_filter( $sections );
550 }
551
552 public static function getCurrentSettings( $settings ) {
553 if ( self::isSectionMode( $settings ) ) {
554 $currentSection = self::getActiveSection( $settings );
555 $currentSettings = $settings['sections'][ $currentSection ]['settings'] ?? [];
556 } else {
557 $currentSettings = $settings['settings'] ?? [];
558 }
559
560 return $currentSettings;
561 }
562
563 public static function getActiveSection( $settings ) {
564 if ( empty( $settings['sections'] ) ) {
565 return false;
566 }
567
568 $sections = array_keys( $settings['sections'] );
569 $sections = array_map( 'strtolower', $sections );
570 $default = current( $sections );
571 $current = strtolower( Param::get( 'section', $default ) );
572
573 return in_array( $current, $sections, true ) ? $current : $default;
574 }
575
576 private static function isSectionMode( $settings ): bool {
577 return ! empty( $settings['sections'] ) && is_array( $settings['sections'] );
578 }
579 }
580