PluginProbe
CBX Map for Google Map & OpenStreetMap / trunk
CBX Map for Google Map & OpenStreetMap vtrunk
trunk 1.1.10 1.1.11 1.1.12 1.1.5 1.1.6 1.1.7 1.1.8 1.1.9 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5
cbxgooglemap / includes / CBXGooglemapSettings.php

CBXGooglemapSettings.php in CBX Map for Google Map & OpenStreetMap trunk, at includes/CBXGooglemapSettings.php

1,231 lines 45.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace Cbx\Googlemap;
3
4 // If this file is called directly, abort.
5 if ( ! defined( 'WPINC' ) ) {
6 die;
7 }
8
9 use Cbx\Googlemap\Helpers\CBXGooglemapHelper;
10
11 /**
12 * Wordpress Settings API wrapper class
13 *
14 * @version 1.2
15 * Last update: 27.09.2016
16 *
17 * Initial version Forked from https://github.com/tareq1988/wordpress-settings-api-class
18 *
19 */
20 final class CBXGooglemapSettings
21 {
22 /**
23 * settings sections array
24 *
25 * @var array
26 */
27 private $settings_sections = [];
28
29 /**
30 * Settings fields array
31 *
32 * @var array
33 */
34 private $settings_fields = [];
35
36 /**
37 * Singleton instance
38 *
39 * @var object
40 */
41 private static $_instance;
42
43 public function __construct()
44 {
45
46 }
47
48 public static function instance()
49 {
50 if (is_null(self::$_instance)) {
51 self::$_instance = new self();
52 }
53
54 return self::$_instance;
55 }//end method instance
56
57 /**
58 * Cloning is forbidden.
59 *
60 * @since 2.0.0
61 */
62 public function __clone()
63 {
64 cbxgooglemap_doing_it_wrong(__FUNCTION__, esc_html__('Cloning is forbidden.', 'cbxgooglemap'), '2.0.0');
65 }//end method clone
66
67 /**
68 * Unserializing instances of this class is forbidden.
69 *
70 * @since 2.0.0
71 */
72 public function __wakeup()
73 {
74 cbxgooglemap_doing_it_wrong(__FUNCTION__, esc_html__('Unserializing instances of this class is forbidden.', 'cbxgooglemap'), '2.0.0');
75 }//end method wakeup
76
77 /**
78 * Set settings sections
79 *
80 * @param array $sections setting sections array
81 */
82 function set_sections($sections)
83 {
84 $this->settings_sections = $sections;
85
86 return $this;
87 }
88
89 /**
90 * Add a single section
91 *
92 * @param array $section
93 */
94 function add_section($section)
95 {
96 $this->settings_sections[] = $section;
97
98 return $this;
99 }
100
101 /**
102 * Set settings fields
103 *
104 * @param array $fields settings fields array
105 */
106 function set_fields($fields)
107 {
108 $this->settings_fields = $fields;
109
110 return $this;
111 }
112
113 function add_field($section, $field)
114 {
115 $defaults = [
116 'name' => '',
117 'label' => '',
118 'desc' => '',
119 'type' => 'text',
120 ];
121
122 $arg = wp_parse_args($field, $defaults);
123 $this->settings_fields[$section][] = $arg;
124
125 return $this;
126 }//end method add_field
127
128
129 function admin_init()
130 {
131 //register settings sections
132 foreach ($this->settings_sections as $section) {
133 if (false == get_option($section['id'])) {
134 $section_default_value = $this->getDefaultValueBySection($section['id']);
135 add_option($section['id'], $section_default_value);
136 } else {
137 $section_default_value = $this->getMissingDefaultValueBySection($section['id']);
138 update_option($section['id'], $section_default_value);
139 }
140
141 if (isset($section['desc']) && ! empty($section['desc'])) {
142 $section['desc'] = '<div class="inside">'.$section['desc'].'</div>';
143 //$callback = create_function('', 'echo "' . str_replace('"', '\"', $section['desc']) . '";');
144 $callback = function () use ($section) {
145 echo str_replace('"', '\"', $section['desc']); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
146 };
147 } elseif (isset($section['callback'])) {
148 $callback = $section['callback'];
149 } else {
150 $callback = null;
151 }
152
153 add_settings_section($section['id'], $section['title'], $callback, $section['id']);
154 }
155
156 //register settings fields
157 foreach ($this->settings_fields as $section => $field) {
158 foreach ($field as $option) {
159
160 $name = $option['name'];
161 $type = isset($option['type']) ? $option['type'] : 'text';
162 $label = isset($option['label']) ? $option['label'] : '';
163 $callback = isset($option['callback']) ? $option['callback'] : [$this, 'callback_'.$type];
164
165 $label_for = $this->settings_clean_label_for("{$section}_{$option['name']}");
166
167 $args = [
168 'id' => $option['name'],
169 'class' => isset($option['class']) ? $option['class'] : $name,
170 'label_for' => $label_for,
171 'desc' => isset($option['desc']) ? $option['desc'] : '',
172 'name' => $label,
173 'section' => $section,
174 'size' => isset($option['size']) ? $option['size'] : null,
175 'min' => isset($option['min']) ? $option['min'] : '',
176 'max' => isset($option['max']) ? $option['max'] : '',
177 'step' => isset($option['step']) ? $option['step'] : '',
178 'options' => isset($option['options']) ? $option['options'] : '',
179 'default' => isset($option['default']) ? $option['default'] : '',
180 'sanitize_callback' => isset($option['sanitize_callback']) ? $option['sanitize_callback'] : '',
181 'placeholder' => isset($option['placeholder']) ? $option['placeholder'] : '',
182 'type' => $type,
183 'optgroup' => isset($option['optgroup']) ? intval($option['optgroup']) : 0,
184 'multi' => isset($option['multi']) ? intval($option['multi']) : 0,
185 'fields' => isset($option['fields']) ? $option['fields'] : [],
186 'sortable' => isset($option['sortable']) ? intval($option['sortable']) : 0,
187 'allow_new' => isset($option['allow_new']) ? intval($option['allow_new']) : 0,
188 //only works for repeatable
189 'allow_clear' => isset($option['allow_clear']) ? intval($option['allow_clear']) : 0,
190 //only works for repeatable
191 'check_content' => isset($option['check_content']) ? $option['check_content'] : '',
192 'inline' => isset($option['inline']) ? absint($option['inline']) : 1,
193 ];
194
195
196 add_settings_field("{$section}[{$name}]", $label, $callback, $section, $section, $args);
197 }
198 }
199
200 // creates our settings in the options table
201 foreach ($this->settings_sections as $section) {
202 // phpcs:ignore PluginCheck.CodeAnalysis.SettingSanitization.register_settingDynamic
203 register_setting($section['id'], $section['id'], [$this, 'sanitize_options']);
204 }
205 }//end method admin_init
206
207 /**
208 * Prepares default values by section
209 *
210 * @param $section_id
211 *
212 * @return array
213 */
214 function getDefaultValueBySection($section_id)
215 {
216 $default_values = [];
217
218 $fields = $this->settings_fields[$section_id];
219 foreach ($fields as $field) {
220 $default_values[$field['name']] = isset($field['default']) ? $field['default'] : '';
221 }
222
223 return $default_values;
224 }//end getDefaultValueBySection
225
226 /**
227 * Prepares default values by section
228 *
229 * @param $section_id
230 *
231 * @return array
232 */
233 function getMissingDefaultValueBySection($section_id)
234 {
235 $section_value = get_option($section_id);
236 $fields = $this->settings_fields[$section_id];
237
238 foreach ($fields as $field) {
239 if ( ! isset($section_value[$field['name']])) {
240 $section_value[$field['name']] = isset($field['default']) ? $field['default'] : '';
241 }
242
243 }
244
245 return $section_value;
246 }//end getMissingDefaultValueBySection
247
248 /**
249 * Get field description for display
250 *
251 * @param $args
252 *
253 * @return string
254 */
255 public function get_field_description($args)
256 {
257 if ( ! empty($args['desc'])) {
258 $desc = sprintf('<p class="description">%s</p>', $args['desc']);
259 } else {
260 $desc = '';
261 }
262
263 return $desc;
264 }//end method get_field_description
265
266 /**
267 * Displays heading field using h3
268 *
269 * @param array $args
270 *
271 * @return string
272 */
273 function callback_heading($args)
274 {
275 $plus_svg = cbxgooglemap_esc_svg(cbxgooglemap_load_svg('icon_plus'));
276 $minus_svg = cbxgooglemap_esc_svg(cbxgooglemap_load_svg('icon_minus'));
277
278 $html = '<h3 class="setting_heading"><span class="setting_heading_title">'.esc_html($args['name']).'</span><a title="'.esc_attr__('Click to show hide',
279 'cbxgooglemap').'" class="setting_heading_toggle button outline primary icon icon-only icon-inline" href="#"><i class="cbx-icon setting_heading_toggle_plus">'.$plus_svg.'</i><i class="cbx-icon setting_heading_toggle_minus">'.$minus_svg.'</i></a></h3>';
280 $html .= $this->get_field_description($args);
281
282 echo $html;//phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
283 }//end method callback_heading
284
285 /**
286 * Displays sub heading field using h4
287 *
288 * @param array $args
289 *
290 * @return void
291 */
292 function callback_subheading($args)
293 {
294 $html = '<h4 class="setting_subheading">'.$args['name'].'</h4>';
295 $html .= $this->get_field_description($args);
296
297 echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
298 }//end method callback_subheading
299
300
301 /**
302 * Displays a text field for a settings field
303 *
304 * @param array $args
305 * @param $value
306 *
307 * @return void
308 */
309 function callback_text($args, $value = null)
310 {
311 if ($value === null) {
312 $value = esc_attr($this->get_option($args['id'], $args['section'], $args['default']));
313 }
314 $size = isset($args['size']) && ! is_null($args['size']) ? $args['size'] : 'regular';
315 $type = isset($args['type']) ? $args['type'] : 'text';
316
317 $html_id = "{$args['section']}_{$args['id']}";
318 $html_id = $this->settings_clean_label_for($html_id);
319
320 $html = sprintf('<input autocomplete="none" onfocus="this.removeAttribute(\'readonly\');" readonly type="%1$s" class="%2$s-text" id="%6$s" name="%3$s[%4$s]" value="%5$s"/>', $type, $size, $args['section'], $args['id'], $value, $html_id);
321 $html .= $this->get_field_description($args);
322
323 echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
324 }//end callback_text
325
326 /**
327 * Displays an url field for a settings field
328 *
329 * @param array $args
330 * @param null $value
331 *
332 * @return void
333 */
334 function callback_url($args, $value = null)
335 {
336 $this->callback_text($args, $value);
337 }//end method callback_url
338
339 /**
340 * Displays a number field for a settings field
341 *
342 * @param array $args
343 *
344 * @return void
345 */
346 function callback_number($args, $value = null)
347 {
348 if ($value === null) {
349 $value = esc_attr($this->get_option($args['id'], $args['section'], $args['default']));
350 }
351
352 $size = isset($args['size']) && ! is_null($args['size']) ? $args['size'] : 'regular';
353 $type = isset($args['type']) ? $args['type'] : 'number';
354 $placeholder = empty($args['placeholder']) ? '' : ' placeholder="'.$args['placeholder'].'"';
355 $min = empty($args['min']) ? '' : ' min="'.$args['min'].'"';
356 $max = empty($args['max']) ? '' : ' max="'.$args['max'].'"';
357 $step = empty($args['max']) ? '' : ' step="'.$args['step'].'"';
358
359 $html_id = "{$args['section']}_{$args['id']}";
360 $html_id = $this->settings_clean_label_for($html_id);
361
362 $html = sprintf('<input type="%1$s" class="%2$s-number" id="%10$s" name="%3$s[%4$s]" value="%5$s"%6$s%7$s%8$s%9$s/>', $type, $size, $args['section'], $args['id'], $value, $placeholder, $min, $max, $step, $html_id);
363 $html .= $this->get_field_description($args);
364 echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
365 }//end method callback_number
366
367 /**
368 * Displays a multicheckbox a settings field
369 *
370 * @param array $args
371 * @param $value
372 *
373 * @return void
374 */
375 function callback_radio($args, $value = null)
376 {
377 if ($value === null) {
378 $value = $this->get_option($args['id'], $args['section'], $args['default']);
379 }
380
381 $display_inline = isset($args['inline']) ? absint($args['inline']) : 1;
382 $display_inline_class = ($display_inline) ? 'radio_fields_inline' : '';
383
384 $html = '<div class="radio_fields magic_radio_fields '.esc_attr($display_inline_class).'">';
385
386 foreach ($args['options'] as $key => $label) {
387
388 $html_id = "{$args['section']}_{$args['id']}_{$key}";
389 $html_id = $this->settings_clean_label_for($html_id);
390
391
392 $html .= '<div class="magic-radio-field">';
393 //$html .= sprintf( '<input type="radio" class="radio" id="wpuf-%5$s" name="%1$s[%2$s]" value="%3$s" %4$s />', $args['section'], $args['id'], $key, checked( $value, $key, false ), $html_id );
394 $html .= sprintf('<input type="radio" class="magic-radio" id="wpuf-%5$s" name="%1$s[%2$s]" value="%3$s" %4$s />', $args['section'], $args['id'], $key, checked($value, $key, false), $html_id);
395 $html .= sprintf('<label for="wpuf-%1$s">', $html_id);
396 $html .= sprintf('%1$s</label>', $label);
397 $html .= '</div>';
398 }
399
400
401 $html .= $this->get_field_description($args);
402 $html .= '</div>';
403
404 echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
405 }//end method callback_radio
406
407 /**
408 * Displays a checkbox for a settings field
409 *
410 * @param array $args
411 * @param $value
412 *
413 * @return void
414 */
415 function callback_checkbox($args, $value = null)
416 {
417 if ($value === null) {
418 $value = esc_attr($this->get_option($args['id'], $args['section'], $args['default']));
419 }
420
421 $html_id = "{$args['section']}_{$args['id']}";
422 $html_id = $this->settings_clean_label_for($html_id);
423
424 $html = '<div class="checkbox_field magic_checkbox_field">';
425 $html .= sprintf('<input type="hidden" name="%1$s[%2$s]" value="off" />', $args['section'], $args['id']);
426 $html .= sprintf('<input type="checkbox" class="magic-checkbox" id="wpuf-%4$s" name="%1$s[%2$s]" value="on" %3$s />', $args['section'], $args['id'], checked($value, 'on', false), $html_id);
427 $html .= sprintf('<label for="wpuf-%1$s">', $html_id);
428 $html .= sprintf('%1$s</label>', $args['desc']);
429 $html .= '</div>';
430
431 echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
432 }//end method callback_checkbox
433
434 /**
435 * Displays a multicheckbox settings field
436 *
437 * @param array $args
438 * @param $value
439 *
440 * @return void
441 */
442 function callback_multicheck($args, $value = null)
443 {
444 $sortable = isset($args['sortable']) ? intval($args['sortable']) : 0;
445
446 if ($value === null) {
447 $value = $this->get_option($args['id'], $args['section'], $args['default']);
448 }
449
450 if ( ! is_array($value)) {
451 $value = [];
452 }
453
454 $options = $args['options'];//this can be regular array or associative array
455 $value = array_values($value);
456
457 $display_inline = isset($args['inline']) ? absint($args['inline']) : 1;
458 $display_inline_class = '';
459
460 if ($sortable) {
461 $display_inline = 0;
462 }
463
464 $display_inline_class .= ($display_inline) ? 'checkbox_fields_inline' : '';
465
466
467 $sortable_class = ($sortable) ? 'checkbox_fields_sortable' : '';
468
469 $html = '<p class="grouped gapless grouped_buttons checkbox_fields_check_actions"><a href="#" class="button primary checkbox_fields_check_action_call">'.esc_html__('Check All', 'cbxgooglemap').'</a><a href="#" class="button outline checkbox_fields_check_action_ucall">'.esc_html__('Uncheck All', 'cbxgooglemap').'</a></p>';
470 $html .= '<div class="checkbox_fields magic_checkbox_fields '.esc_attr($sortable_class).' '.esc_attr($display_inline_class).'">';
471
472 if ($sortable) {
473 $options = $this->sort_options_by_saved_values($options, $value);
474 }
475
476 foreach ($options as $key => $label) {
477 $checked = in_array($key, $value) ? ' checked="checked" ' : '';
478
479
480 $html_id = "{$args['section']}_{$args['id']}_{$key}";
481 $html_id = $this->settings_clean_label_for($html_id);
482
483 $html .= '<div class="checkbox_field magic_checkbox_field" data-key="'.esc_attr($key).'">';
484 if ($sortable) {
485 $html .= '<span class="checkbox_field_handle" style="cursor: grab;"></span>';
486 }
487
488 $html .= sprintf('<input type="hidden" name="%1$s[%2$s][%3$s]" value="" />', $args['section'], $args['id'], $key);
489 $html .= sprintf('<input type="checkbox" class="magic-checkbox" id="wpuf-%5$s" name="%1$s[%2$s][%3$s]" value="%3$s" %4$s />', $args['section'], $args['id'], $key, $checked, $html_id);
490 $html .= sprintf('<label for="wpuf-%1$s">', $html_id);
491 $html .= sprintf('%1$s</i></label>', $label);
492 $html .= '</div>';
493 }
494
495 $html .= $this->get_field_description($args);
496 $html .= '</div>';
497
498 echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
499 }//end method callback_multicheck
500
501
502 /**
503 * Displays a select box for a settings field
504 *
505 * @param $args
506 *
507 * @return void
508 */
509 function callback_select($args)
510 {
511 $value = $this->get_option($args['id'], $args['section'], $args['default']);
512
513 $multi = isset($args['multi']) ? intval($args['multi']) : 0;
514 $multi_name = ($multi) ? '[]' : '';
515 $multi_attr = ($multi) ? 'multiple' : '';
516
517 if ($multi && ! is_array($value)) {
518 $value = [];
519 }
520
521 /*if ( ! is_array( $value ) ) {
522 $value = [];
523 }*/
524
525 $size = isset($args['size']) && ! is_null($args['size']) ? $args['size'] : 'regular selecttwo-select';
526
527 if ($args['placeholder'] == '') {
528 $args['placeholder'] = esc_html__('Please Select', 'cbxgooglemap');
529 }
530
531 $html = sprintf('<input type="hidden" name="%1$s[%2$s][]" value="" />', $args['section'], $args['id']);
532 $html .= sprintf('<div class="selecttwo-select-wrapper"><select '.$multi_attr.' class="%1$s" name="%2$s[%3$s]'.$multi_name.'" id="%2$s[%3$s]" style="min-width: 150px !important;" placeholder="%4$s" data-placeholder="%4$s">', $size, $args['section'], $args['id'], $args['placeholder']);
533
534 if (isset($args['optgroup']) && $args['optgroup']) {
535 foreach ($args['options'] as $opt_grouplabel => $option_vals) {
536 $html .= '<optgroup label="'.$opt_grouplabel.'">';
537
538 if ( ! is_array($option_vals)) {
539 $option_vals = [];
540 }
541
542 foreach ($option_vals as $key => $val) {
543 $selected = in_array($key, $value) ? ' selected="selected" ' : '';
544 $html .= sprintf('<option value="%s" '.$selected.'>%s</option>', $key, $val);
545 }
546 $html .= '</optgroup>';
547 }
548 } else {
549 $option_vals = $args['options'];
550
551 foreach ($option_vals as $key => $val) {
552 if ($multi) {
553 $selected = in_array($key, $value) ? ' selected="selected" ' : '';
554 $html .= sprintf('<option value="%s" '.$selected.'>%s</option>', $key, $val);
555 } else {
556 $html .= sprintf('<option value="%s"%s>%s</option>', $key, selected($value, $key, false), $val);
557 }
558 }
559 }
560
561 $html .= '</select></div>';
562 $html .= $this->get_field_description($args);
563
564 echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
565 }//end method callback_select
566
567 /**
568 * Displays a select box for a settings field
569 *
570 * @param $args
571 *
572 * @return void
573 */
574 function callback_page($args)
575 {
576 $edit_svg = cbxgooglemap_esc_svg(cbxgooglemap_load_svg('icon_edit'));
577 $external_svg = cbxgooglemap_esc_svg(cbxgooglemap_load_svg('icon_external'));
578
579 $value = absint($this->get_option($args['id'], $args['section'], intval($args['default'])));
580 $size = isset($args['size']) && ! is_null($args['size']) ? $args['size'] : 'regular selecttwo-select';
581 $check_content = isset($args['check_content']) && ! is_null($args['check_content']) ? $args['check_content'] : '';
582
583 $allow_clear = isset($args['allow_clear']) ? intval($args['allow_clear']) : 0;
584
585 $page_content = '';
586 $page_shortcode_note = '';
587 $shortcode_found_class = '';
588
589
590 $html = '<div class="setting_pages_actions_wrapper">';
591
592 $page_html = '<div class="setting_pages_actions">';
593 if ($value > 0) {
594 if ($check_content != '') {
595 $page = get_post($value);
596 $page_content = $page->post_content;
597 if (has_shortcode($page_content, $check_content)) {
598 $shortcode_found_class = 'description_note_on';
599 /* translators: %s: content */
600 $page_shortcode_note = sprintf(esc_html__('This page has shortcode %s', 'cbxgooglemap'), $check_content);
601 } else {
602 $shortcode_found_class = 'description_note_off';
603 /* translators: %s: content */
604 $page_shortcode_note = sprintf(esc_html__('This page doesn\'t have shortcode %s', 'cbxgooglemap'), $check_content);
605 }
606 }
607
608 //edit
609 if (current_user_can('edit_post', $value)) {
610 $page_html .= '<a class="setting_pages_action setting_pages_action_edit button primary icon icon-only small" target="_blank" title="'.esc_attr__('Edit', 'cbxgooglemap').'" href="'.get_edit_post_link($value).'"><i class="cbx-icon">'.$edit_svg.'</i></a>';
611 }
612
613 //view
614 $page_html .= '<a class="setting_pages_action setting_pages_action_view button outline primary icon icon-only small" title="'.esc_attr__('View', 'cbxgooglemap').'" target="_blank" href="'.get_the_permalink($value).'"><i class="cbx-icon">'.$external_svg.'</i></a>';
615 }
616
617 $page_html .= '</div>';
618
619
620 if ($args['placeholder'] == '') {
621 $placeholder = $args['placeholder'] = esc_html__('Please Select', 'cbxgooglemap');
622 } else {
623 $placeholder = esc_attr($args['placeholder']);
624 }
625
626
627 $html .= sprintf('<input type="hidden" name="%1$s[%2$s][]" value="" />', $args['section'], $args['id']);
628 $html .= sprintf('<div class="selecttwo-select-wrapper" data-placeholder="'.$placeholder.'" data-allow-clear="'.$allow_clear.'"><select class="%1$s" name="%2$s[%3$s]" id="%2$s[%3$s]" style="min-width: 150px !important;" >', $size, $args['section'], $args['id']);
629
630
631 $option_vals = $args['options'];
632 foreach ($option_vals as $key => $val) {
633 $html .= sprintf('<option value="%s"%s>%s</option>', $key, selected($value, $key, false), $val);
634
635 }
636
637
638 $html .= '</select></div>'.$page_html;
639 $html .= '</div>'; //.setting_pages_actions_wrapper
640
641 if ($page_shortcode_note != '') {
642 $html .= '<p class="description_note '.esc_attr($shortcode_found_class).'">'.$page_shortcode_note.'</p>';
643 }
644
645 $html .= $this->get_field_description($args);
646
647 echo $html;//phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
648 }//end method callback_page
649
650
651 /**
652 * Displays a textarea for a settings field
653 *
654 * @param array $args
655 * @param $value
656 *
657 * @return void
658 */
659 function callback_textarea($args, $value = null)
660 {
661 if ($value === null) {
662 $value = esc_textarea($this->get_option($args['id'], $args['section'], $args['default']));
663 }
664 $size = isset($args['size']) && ! is_null($args['size']) ? $args['size'] : 'regular';
665
666 $html_id = "{$args['section']}_{$args['id']}";
667 $html_id = $this->settings_clean_label_for($html_id);
668
669 $html = sprintf('<textarea rows="5" cols="55" class="%1$s-text" id="%5$s" name="%2$s[%3$s]">%4$s</textarea>', $size, $args['section'], $args['id'], $value, $html_id);
670 $html .= $this->get_field_description($args);
671
672 echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
673 }//end method callback_textarea
674
675 /**
676 * Displays a rich text textarea for a settings field
677 *
678 * @param array $args
679 * @param $value
680 *
681 * @return void
682 */
683 function callback_wysiwyg($args, $value = null)
684 {
685 if ($value === null) {
686 $value = $this->get_option($args['id'], $args['section'], $args['default']);
687 }
688 $size = isset($args['size']) && ! is_null($args['size']) ? $args['size'] : '500px';
689
690 echo '<div style="max-width: '.esc_attr($size).';">';
691
692 $html_id = "{$args['section']}_{$args['id']}";
693 $html_id = $this->settings_clean_label_for($html_id);
694
695 $editor_settings = [
696 'teeny' => true,
697 'textarea_name' => $args['section'].'['.$args['id'].']',
698 'textarea_rows' => 10
699 ];
700 if (isset($args['options']) && is_array($args['options'])) {
701 $editor_settings = array_merge($editor_settings, $args['options']);
702 }
703
704 //wp_editor( $value, $args['section'] . '-' . $args['id'], $editor_settings );
705 wp_editor($value, $html_id, $editor_settings);
706
707 echo '</div>';
708
709 echo $this->get_field_description($args); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
710 }//end method callback_wysiwyg
711
712 /**
713 * Displays a file upload field for a settings field
714 *
715 * @param array $args settings field args
716 */
717 function callback_file($args)
718 {
719 $value = esc_attr($this->get_option($args['id'], $args['section'], $args['default']));
720 $size = isset($args['size']) && ! is_null($args['size']) ? $args['size'] : 'regular';
721 $id = $args['section'].'['.$args['id'].']';
722 $label = isset($args['options']['button_label']) ? $args['options']['button_label'] : esc_html__('Choose File',
723 'cbxgooglemap');
724
725 $html = '<div class="cbxchota-setting_input_file_wrap">';
726 $html .= sprintf('<input type="text" class="%1$s-text wpsa-url" id="%2$s[%3$s]" name="%2$s[%3$s]" value="%4$s"/>',
727 $size, $args['section'], $args['id'], $value);
728
729 $icon_extra_class = '';
730 $marker_icon = '';
731 $trash_extra_class = '';
732 if ($value === '') {
733 $icon_extra_class = 'cbxchota-setting_marker_hide';
734 $file_picked_class = 'cbxchota-setting_left_space';
735 $trash_extra_class = 'cbxchota-setting_trash_hide';
736 } else {
737 $marker_icon = ' background-image: url(\''.esc_url($value).'\') ;';
738 $file_picked_class = 'cbxchota-setting_filepicked';
739 }
740 $html .= '<span style="'.esc_attr($marker_icon).'" class="cbxchota-setting_marker_preview '.esc_attr($icon_extra_class).'"></span>';
741
742 $html .= '<input type="button" class="button cbxchota-setting_filepicker_btn wpsa-browse '.esc_attr($file_picked_class).'" value="'.esc_attr($label).'" />';
743 $html .= '<span class="cbxchota-setting_trash dashicons dashicons-no-alt '.esc_attr($trash_extra_class).'"></span>';
744 $html .= '</div>';
745 $html .= $this->get_field_description($args);
746
747 echo $html;// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
748 }//end method callback_file
749
750
751 /**
752 * Displays a color picker field for a settings field
753 *
754 * @param array $args
755 * @param $value
756 *
757 * @return void
758 */
759 function callback_color($args, $value = null)
760 {
761
762 if ($value === null) {
763 $value = esc_attr($this->get_option($args['id'], $args['section'], $args['default']));
764 }
765
766 $size = isset($args['size']) && ! is_null($args['size']) ? $args['size'] : 'regular';
767
768 $html_id = "{$args['section']}_{$args['id']}";
769 $html_id = $this->settings_clean_label_for($html_id);
770
771 $choose_color = esc_html__('Choose Color', 'cbxgooglemap');
772
773 $html = '<div class="setting-color-picker-wrapper">';
774 $html .= sprintf('<input type="hidden" class="%1$s-text setting-color-picker" id="%6$s" name="%2$s[%3$s]" value="%4$s" /><span data-current-color="%4$s" class="button setting-color-picker-fire">%7$s</span>', $size, $args['section'], $args['id'], $value, $args['default'], $html_id, $choose_color);
775 $html .= '</div>';
776
777 $html .= $this->get_field_description($args);
778
779 echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
780 }//end callback_color
781
782 /**
783 * Displays a password field for a settings field
784 *
785 * @param array $args
786 *
787 * @return void
788 */
789 function callback_password($args)
790 {
791 $value = esc_attr($this->get_option($args['id'], $args['section'], $args['default']));
792 $size = isset($args['size']) && ! is_null($args['size']) ? $args['size'] : 'regular';
793
794 $html = sprintf('<input type="password" class="%1$s-text" id="%2$s[%3$s]" name="%2$s[%3$s]" value="%4$s"/>', $size, $args['section'], $args['id'], $value);
795 $html .= $this->get_field_description($args);
796
797 echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
798 }//end method callback_password
799
800
801 /**
802 * Displays a email field for a settings field
803 *
804 * @param array $args settings field args
805 */
806 function callback_email($args)
807 {
808 $value = esc_attr($this->get_option($args['id'], $args['section'], $args['default']));
809 $size = isset($args['size']) && ! is_null($args['size']) ? $args['size'] : 'regular';
810 $type = isset($args['type']) ? $args['type'] : 'text';
811
812 $html_id = "{$args['section']}_{$args['id']}";
813 $html_id = $this->settings_clean_label_for($html_id);
814
815 $html = sprintf('<input autocomplete="none" onfocus="this.removeAttribute(\'readonly\');" readonly type="%1$s" class="%2$s-text" id="%6$s" name="%3$s[%4$s]" value="%5$s"/>', $type, $size, $args['section'], $args['id'], $value, $html_id);
816 $html .= $this->get_field_description($args);
817
818 echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
819 }//end method callback_email
820
821 /**
822 * Displays custom file extension checker checkbox for a settings field
823 *
824 * @param array $args settings field args
825 */
826 function callback_file_extensions_checker($args)
827 {
828 $stored_ext_arr = $this->get_option($args['id'], $args['section'], $args['default']);
829 $image_ext_arr = CBXGooglemapHelper::getImageExts();
830
831 $html = sprintf('<input type="hidden" name="%1$s[%2$s][]" value="0" />', $args['section'], $args['id']);
832
833 $html .= '<div class="checkbox_fields magic_checkbox_fields checkbox_fields_inline">';
834
835 foreach ($image_ext_arr as $index => $extension) {
836 // checkbox html
837 $html .= '<div class="checkbox_field magic_checkbox_field">';
838 $html .= sprintf(' <input type="checkbox" class="magic-checkbox"
839 id="%1$s[%2$s][%3$s]" name="%1$s[%2$s][]" value="%4$s" %5$s /><label for="%1$s[%2$s][%3$s]" class="checkbox-inline-extend">%4$s</label>',
840 $args['section'],
841 $args['id'],
842 $index,
843 ucfirst($extension),
844 checked((is_array($stored_ext_arr) && in_array($extension, $stored_ext_arr)), '1', false)
845 );
846
847 $html .= '</div>';
848 }
849
850 $html .= '</div>';
851
852 echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
853 }//end method callback_file_extensions_checker
854
855 /**
856 * Displays a text field for a settings field
857 *
858 * @param array $args settings field args
859 */
860 function callback_slug($args)
861 {
862 $value = esc_attr($this->get_field($args['id'], $args['section'], $args['default']));
863 $size = isset($args['size']) && ! is_null($args['size']) ? $args['size'] : 'regular';
864
865 //$id = $args['section'] . '[' . $args['id'] . ']';
866 $html_id = "{$args['section']}_{$args['id']}";
867 $html_id = $this->settings_clean_label_for($html_id);
868
869
870 $label = isset($args['options']['button_label']) ?
871 $args['options']['button_label'] :
872 esc_html__('Clear Permalinks', 'cbxgooglemap');
873
874 $html = '<div class="permalink-wrap">';
875 $html .= sprintf('<input type="text" class="chota-inline %1$s-text permalink-slug" id="%5$s" name="%2$s[%3$s]" value="%4$s"/>',
876 $size, $args['section'], $args['id'], $value, $html_id);
877 $html .= '<a href="#" class="button outline primary clear-permalink ld-ext-right">'.esc_html($label).'<span class="ld ld-spin ld-ring"></span></a>';
878 $html .= '</div>';
879 $html .= $this->get_field_description($args);
880
881 echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
882 } //end method callback_slug
883
884 /**
885 * Displays a textarea for a settings field
886 *
887 * @param array $args settings field args
888 */
889 function callback_shortcode($args)
890 {
891 $value = $args['default'];
892 $value_esc = esc_textarea($value);
893 $size = isset($args['size']) && ! is_null($args['size']) ? $args['size'] : 'regular';
894 $class = isset($args['class']) && ! is_null($args['class']) ? $args['class'] : '';
895
896 $required = isset($args['required']) ? 'required' : '';
897
898
899 $html = sprintf('<textarea readonly rows="5" cols="55" class="%1$s-text %6$s" id="%2$s[%3$s]" name="%2$s[%3$s]" %5$s>%4$s</textarea>',
900 $size,
901 $args['section'],
902 $args['id'],
903 $value_esc,
904 $required, $class);
905
906 $html .= '<a data-target-cp="#'.$args['section'].'\\['.$args['id'].'\\]'.'" class="shortcode_demo_btn" href="#">Click to copy shortcode</a>';
907 $html .= $this->get_field_description($args);
908
909
910 $html .= '<div class="shortcode_demo_wrap">'.do_shortcode($value).'</div>';
911
912 echo $html;// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
913 }//end method callback_shortcode
914
915
916 /**
917 * Convert an array to associative if not
918 *
919 * @param $value
920 */
921 /*private function convert_associate($value){
922 if(!$this->is_associate($value) && sizeof($value) > 0){
923 $new_value = array();
924 foreach ($value as $val){
925 $new_value[$val] = ucfirst($val);
926 }
927 return $new_value;
928 }
929
930
931 return $value;
932 }*/
933
934 /**
935 * Clean label_for or id tad
936 *
937 * @param $str
938 *
939 * @return string
940 */
941 public function settings_clean_label_for($str)
942 {
943 $str = str_replace('][', '_', $str);
944 $str = str_replace(']', '_', $str);
945
946 return str_replace('[', '_', $str);
947 }//end settings_clean_label_for
948
949
950 /**
951 * check if any array is associative
952 *
953 * @param array $array
954 *
955 * @return bool
956 */
957 private function is_associate(array $array)
958 {
959 return count(array_filter(array_keys($array), 'is_string')) > 0;
960 }
961
962 /**
963 * Sanitize callback for Settings API
964 */
965 function sanitize_options($options)
966 {
967 foreach ($options as $option_slug => $option_value) {
968 $sanitize_callback = $this->get_sanitize_callback($option_slug);
969
970 // If callback is set, call it
971 if ($sanitize_callback) {
972 $options[$option_slug] = call_user_func($sanitize_callback, $option_value);
973 continue;
974 }
975 }
976
977 return $options;
978 }
979
980 /**
981 * Get sanitization callback for given option slug
982 *
983 * @param string $slug option slug
984 *
985 * @return mixed string or bool false
986 */
987 function get_sanitize_callback($slug = '')
988 {
989 if (empty($slug)) {
990 return false;
991 }
992
993 // Iterate over registered fields and see if we can find proper callback
994 foreach ($this->settings_fields as $section => $options) {
995 foreach ($options as $option) {
996 if ($option['name'] != $slug) {
997 continue;
998 }
999
1000 if (($option['type'] == 'select' && isset($option['multi']) && $option['multi']) || $option['type'] == 'multicheck') {
1001 $option['sanitize_callback'] = [$this, 'sanitize_multi_select_check'];
1002 }
1003
1004 // Return the callback name
1005 return isset($option['sanitize_callback']) && is_callable($option['sanitize_callback']) ? $option['sanitize_callback'] : false;
1006 }
1007 }
1008
1009 return false;
1010 }//end get_sanitize_callback
1011
1012 /**
1013 * Remove empty values from multi select fields (multi select and multi checkbox)
1014 *
1015 * @param $option_value
1016 *
1017 * @return array
1018 */
1019 public function sanitize_multi_select_check($option_value)
1020 {
1021 if (is_array($option_value)) {
1022 return array_filter($option_value);
1023 }
1024
1025 return $option_value;
1026 }
1027
1028 /**
1029 * Sort options based on saved values
1030 *
1031 * @param $options
1032 * @param $saved_values
1033 *
1034 * @return array|mixed
1035 */
1036 public function sort_options_by_saved_values($options, $saved_values)
1037 {
1038 // Ensure saved values is an array
1039 if ( ! is_array($saved_values)) {
1040 return $options;
1041 }
1042
1043 // Filter out any saved keys that are not in options
1044 $saved_values = array_filter($saved_values, function ($key) use ($options) {
1045 return isset($options[$key]);
1046 });
1047
1048 // Sort options based on saved values order, keeping others at the end
1049 $sorted_options = [];
1050 foreach ($saved_values as $key) {
1051 if (isset($options[$key])) {
1052 $sorted_options[$key] = $options[$key];
1053 }
1054 }
1055
1056 // Append any missing options at the end
1057 foreach ($options as $key => $value) {
1058 if ( ! isset($sorted_options[$key])) {
1059 $sorted_options[$key] = $value;
1060 }
1061 }
1062
1063 return $sorted_options;
1064 }//end method sort_options_by_saved_values
1065
1066
1067 /**
1068 * Get the value of a settings field
1069 *
1070 * @param string $option settings field name
1071 * @param string $section the section name this field belongs to
1072 * @param string $default default text if it's not found
1073 *
1074 * @return string
1075 */
1076 function get_option($option, $section, $default = '')
1077 {
1078 $options = get_option($section, []);
1079
1080 if (isset($options[$option])) {
1081 return $options[$option];
1082 }
1083
1084 return $default;
1085 }//end method get_option
1086
1087 /**
1088 * Get the value of a settings field
1089 *
1090 * @param string $option settings field name
1091 * @param string $section the section name this field belongs to
1092 * @param string $default default text if it's not found
1093 *
1094 * @return string
1095 */
1096 function get_field($option, $section, $default = '')
1097 {
1098 $options = get_option($section, []);
1099
1100 if (isset($options[$option])) {
1101 return $options[$option];
1102 }
1103
1104 return $default;
1105 }//end method get_option
1106
1107 /**
1108 * Show navigations as tab
1109 *
1110 * Shows all the settings section labels as tab
1111 */
1112 function show_navigation()
1113 {
1114 $html = '<nav class="tabs setting-tabs setting-tabs-nav mb-0">';
1115
1116 $i = 0;
1117
1118 $mobile_navs = '<div class="selecttwo-select-wrapper setting-select-wrapper"><select data-minimum-results-for-search="Infinity" class="setting-select setting-select-nav selecttwo-select">';
1119
1120 foreach ($this->settings_sections as $tab) {
1121 $active_class = ($i === 0) ? 'active' : '';
1122 $active_select = ($i === 0) ? ' selected ' : '';
1123
1124
1125 $html .= sprintf('<a data-tabid="'.esc_attr($tab['id']).'" href="#%1$s" class="%3$s" id="%1$s-tab">%2$s</a>',
1126 $tab['id'], $tab['title'], $active_class);
1127 $mobile_navs .= '<option '.esc_attr($active_select).' value="'.esc_attr($tab['id']).'">'.esc_attr($tab['title']).'</option>';
1128 $i++;
1129 }
1130
1131
1132 $mobile_navs .= '</select></div>';
1133 $html .= '</nav>';
1134
1135 echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1136 echo $mobile_navs; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1137 }//end method show_navigation
1138
1139 /**
1140 * Show the section settings forms
1141 *
1142 * This function displays every sections in a different form
1143 */
1144 function show_forms()
1145 {
1146 ?>
1147 <div id="setting-tabs-contents">
1148 <div id="global_setting_group_actions" class="mb-0">
1149 <?php do_action('cbxgooglemap_setting_group_actions_start'); ?>
1150 <a class="button outline primary global_setting_group_action global_setting_group_action_open pull-right"
1151 href="#"><?php esc_html_e('Toggle All Sections', 'cbxgooglemap'); ?></a>
1152 <?php do_action('cbxgooglemap_setting_group_actions_end'); ?>
1153 <div class="clear clearfix"></div>
1154 </div>
1155 <div class="metabox-holder">
1156 <?php
1157 $i = 0;
1158 foreach ($this->settings_sections as $form):
1159 $display_style = ($i === 0) ? '' : 'display: none;';
1160 ?>
1161 <div id="<?php echo esc_attr($form['id']); ?>" class="global_setting_group"
1162 style="<?php echo $display_style; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1163 ?>">
1164 <form method="post" action="options.php" class="cbxgooglemap_setting_form">
1165 <?php
1166 do_action('cbxgooglemap_setting_form_start', $form);
1167 do_action('cbxgooglemap_setting_form_top_'.$form['id'], $form);
1168
1169 settings_fields($form['id']);
1170 do_settings_sections($form['id']);
1171
1172 do_action('cbxgooglemap_setting_form_bottom_'.$form['id'], $form);
1173 do_action('cbxgooglemap_setting_form_end', $form);
1174 ?>
1175 <div class="global_setting_submit_buttons_wrap">
1176 <?php do_action('cbxgooglemap_setting_submit_buttons_start', $form['id']); ?>
1177 <?php submit_button(esc_html__('Save Settings', 'cbxgooglemap'),
1178 'button primary submit_setting', 'submit', true,
1179 ['id' => 'submit_'.esc_attr($form['id'])]);
1180
1181
1182 $security = wp_create_nonce('cbxgooglemap_settings_nonce');
1183
1184 $settings_export_url = add_query_arg([
1185 'cbxgooglemap_settings_export' => 1,
1186 'security' => $security,
1187 'section' => $form['id']
1188 ], site_url());
1189
1190 $more_v_svg = cbxgooglemap_esc_svg(cbxgooglemap_load_svg('icon_more_v'));
1191
1192 echo '<details class="dropdown ml-10">';
1193 echo '<summary class="button icon icon-only outline primary icon-inline"><i class="cbx-icon">'.$more_v_svg.'</i></summary>';//phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1194 echo '<div class="card card-menu card-menu-right">';
1195 echo '<ul>';
1196 echo '<li><a href="'.esc_url($settings_export_url).'" class="button outline primary submit_export_section">'.esc_attr__('Export Section',
1197 'cbxgooglemap').'</a></li>';
1198 echo '<li><a data-section="'.esc_attr($form['id']).'" href="#" class="button outline primary submit_reset_section">'.esc_attr__('Reset Section',
1199 'cbxgooglemap').'</a></li>';
1200 echo '</ul>';
1201 echo '</div>';
1202 echo '</details>';
1203 ?>
1204
1205
1206 <?php do_action('cbxgooglemap_setting_submit_buttons_end', $form['id']); ?>
1207 </div>
1208 </form>
1209 </div>
1210 <?php
1211 $i++;
1212 endforeach;
1213 ?>
1214 </div>
1215 </div>
1216 <?php
1217 }//end show_forms
1218
1219 /**
1220 * Displays a textarea for a settings field
1221 *
1222 * @param array $args
1223 * @param $value
1224 *
1225 * @return void
1226 */
1227 function callback_html($args, $value = null)
1228 {
1229 echo $this->get_field_description($args);//phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1230 } //end method callback_html
1231 }