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