PluginProbe
CBX Map for Google Map & OpenStreetMap / 2.0.1
CBX Map for Google Map & OpenStreetMap v2.0.1
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 2.0.1, at includes/CBXGooglemapSettings.php

1,295 lines 48.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_file2($args)
718 {
719
720 $value = esc_attr($this->get_option($args['id'], $args['section'], $args['default']));
721 $size = isset($args['size']) && ! is_null($args['size']) ? $args['size'] : 'regular';
722
723 //$id = $args['section'] . '[' . $args['id'] . ']';
724 $html_id = "{$args['section']}_{$args['id']}";
725 $html_id = $this->settings_clean_label_for($html_id);
726
727
728 $label = isset($args['options']['button_label']) ?
729 $args['options']['button_label'] :
730 esc_html__('Choose File', 'cbxgooglemap');
731
732 $html = '<div class="wpsa-browse-wrap">';
733 $html .= sprintf('<input type="text" class="chota-inline %1$s-text wpsa-url" id="%5$s" name="%2$s[%3$s]" value="%4$s"/>', $size, $args['section'], $args['id'], $value, $html_id);
734 $html .= '<input type="button" class="button outline primary wpsa-browse" value="'.$label.'" />';
735 $html .= '</div>';
736 $html .= $this->get_field_description($args);
737
738 echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
739 }//end method callback_file2
740
741 /**
742 * Displays a file upload field for a settings field
743 *
744 * @param array $args settings field args
745 */
746 function callback_file_old($args)
747 {
748
749 $value = esc_attr($this->get_option($args['id'], $args['section'], $args['default']));
750 $size = isset($args['size']) && ! is_null($args['size']) ? $args['size'] : 'regular';
751 $id = $args['section'].'['.$args['id'].']';
752 $label = isset($args['options']['button_label']) ? $args['options']['button_label'] : esc_html__('Choose File', 'cbxgooglemap');
753
754 $html = sprintf('<div class="cbxgooglemapmeta_input_file_wrap"><input type="text" class="%1$s-text wpsa-url" id="%2$s[%3$s]" name="%2$s[%3$s]" value="%4$s"/>', $size, $args['section'], $args['id'], $value);
755
756 $icon_extra_class = '';
757 $marker_icon = '';
758 $trash_extra_class = '';
759 if ($value === '') {
760 $icon_extra_class = 'cbxgooglemapmeta_marker_hide';
761 $file_picked_class = 'cbxgooglemapmeta_left_space';
762 $trash_extra_class = 'cbxgooglemapmeta_trash_hide';
763 } else {
764 $marker_icon = ' background-image: url(\''.$value.'\') ;';
765 $file_picked_class = 'cbxgooglemapmeta_filepicked';
766 }
767 $html .= '<span style="'.$marker_icon.'" class="cbxgooglemapmeta_marker_preview '.esc_attr($icon_extra_class).'"></span>';
768
769 $html .= '<input type="button" class="button cbxgooglemapmeta_filepicker_btn wpsa-browse '.$file_picked_class.'" value="'.$label.'" />';
770 $html .= '<span class="cbxgooglemapmeta_trash dashicons dashicons-no-alt '.esc_attr($trash_extra_class).'"></span>';
771 $html .= $this->get_field_description($args);
772
773 echo $html;// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
774 }//not used
775
776 /**
777 * Displays a file upload field for a settings field
778 *
779 * @param array $args settings field args
780 */
781 function callback_file($args)
782 {
783 $value = esc_attr($this->get_option($args['id'], $args['section'], $args['default']));
784 $size = isset($args['size']) && ! is_null($args['size']) ? $args['size'] : 'regular';
785 $id = $args['section'].'['.$args['id'].']';
786 $label = isset($args['options']['button_label']) ? $args['options']['button_label'] : esc_html__('Choose File',
787 'cbxgooglemap');
788
789 $html = '<div class="cbxchota-setting_input_file_wrap">';
790 $html .= sprintf('<input type="text" class="%1$s-text wpsa-url" id="%2$s[%3$s]" name="%2$s[%3$s]" value="%4$s"/>',
791 $size, $args['section'], $args['id'], $value);
792
793 $icon_extra_class = '';
794 $marker_icon = '';
795 $trash_extra_class = '';
796 if ($value === '') {
797 $icon_extra_class = 'cbxchota-setting_marker_hide';
798 $file_picked_class = 'cbxchota-setting_left_space';
799 $trash_extra_class = 'cbxchota-setting_trash_hide';
800 } else {
801 $marker_icon = ' background-image: url(\''.esc_url($value).'\') ;';
802 $file_picked_class = 'cbxchota-setting_filepicked';
803 }
804 $html .= '<span style="'.esc_attr($marker_icon).'" class="cbxchota-setting_marker_preview '.esc_attr($icon_extra_class).'"></span>';
805
806 $html .= '<input type="button" class="button cbxchota-setting_filepicker_btn wpsa-browse '.esc_attr($file_picked_class).'" value="'.esc_attr($label).'" />';
807 $html .= '<span class="cbxchota-setting_trash dashicons dashicons-no-alt '.esc_attr($trash_extra_class).'"></span>';
808 $html .= '</div>';
809 $html .= $this->get_field_description($args);
810
811 echo $html;// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
812 }//end method callback_file
813
814
815 /**
816 * Displays a color picker field for a settings field
817 *
818 * @param array $args
819 * @param $value
820 *
821 * @return void
822 */
823 function callback_color($args, $value = null)
824 {
825
826 if ($value === null) {
827 $value = esc_attr($this->get_option($args['id'], $args['section'], $args['default']));
828 }
829
830 $size = isset($args['size']) && ! is_null($args['size']) ? $args['size'] : 'regular';
831
832 $html_id = "{$args['section']}_{$args['id']}";
833 $html_id = $this->settings_clean_label_for($html_id);
834
835 $choose_color = esc_html__('Choose Color', 'cbxgooglemap');
836
837 $html = '<div class="setting-color-picker-wrapper">';
838 $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);
839 $html .= '</div>';
840
841 $html .= $this->get_field_description($args);
842
843 echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
844 }//end callback_color
845
846 /**
847 * Displays a password field for a settings field
848 *
849 * @param array $args
850 *
851 * @return void
852 */
853 function callback_password($args)
854 {
855 $value = esc_attr($this->get_option($args['id'], $args['section'], $args['default']));
856 $size = isset($args['size']) && ! is_null($args['size']) ? $args['size'] : 'regular';
857
858 $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);
859 $html .= $this->get_field_description($args);
860
861 echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
862 }//end method callback_password
863
864
865 /**
866 * Displays a email field for a settings field
867 *
868 * @param array $args settings field args
869 */
870 function callback_email($args)
871 {
872 $value = esc_attr($this->get_option($args['id'], $args['section'], $args['default']));
873 $size = isset($args['size']) && ! is_null($args['size']) ? $args['size'] : 'regular';
874 $type = isset($args['type']) ? $args['type'] : 'text';
875
876 $html_id = "{$args['section']}_{$args['id']}";
877 $html_id = $this->settings_clean_label_for($html_id);
878
879 $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);
880 $html .= $this->get_field_description($args);
881
882 echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
883 }//end method callback_email
884
885 /**
886 * Displays custom file extension checker checkbox for a settings field
887 *
888 * @param array $args settings field args
889 */
890 function callback_file_extensions_checker($args)
891 {
892 $stored_ext_arr = $this->get_option($args['id'], $args['section'], $args['default']);
893 $image_ext_arr = CBXGooglemapHelper::getImageExts();
894
895 $html = sprintf('<input type="hidden" name="%1$s[%2$s][]" value="0" />', $args['section'], $args['id']);
896
897 $html .= '<div class="checkbox_fields magic_checkbox_fields checkbox_fields_inline">';
898
899 foreach ($image_ext_arr as $index => $extension) {
900 // checkbox html
901 $html .= '<div class="checkbox_field magic_checkbox_field">';
902 $html .= sprintf(' <input type="checkbox" class="magic-checkbox"
903 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>',
904 $args['section'],
905 $args['id'],
906 $index,
907 ucfirst($extension),
908 checked((is_array($stored_ext_arr) && in_array($extension, $stored_ext_arr)), '1', false)
909 );
910
911 $html .= '</div>';
912 }
913
914 $html .= '</div>';
915
916 echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
917 }//end method callback_file_extensions_checker
918
919 /**
920 * Displays a text field for a settings field
921 *
922 * @param array $args settings field args
923 */
924 function callback_slug($args)
925 {
926 $value = esc_attr($this->get_field($args['id'], $args['section'], $args['default']));
927 $size = isset($args['size']) && ! is_null($args['size']) ? $args['size'] : 'regular';
928
929 //$id = $args['section'] . '[' . $args['id'] . ']';
930 $html_id = "{$args['section']}_{$args['id']}";
931 $html_id = $this->settings_clean_label_for($html_id);
932
933
934 $label = isset($args['options']['button_label']) ?
935 $args['options']['button_label'] :
936 esc_html__('Clear Permalinks', 'cbxgooglemap');
937
938 $html = '<div class="permalink-wrap">';
939 $html .= sprintf('<input type="text" class="chota-inline %1$s-text permalink-slug" id="%5$s" name="%2$s[%3$s]" value="%4$s"/>',
940 $size, $args['section'], $args['id'], $value, $html_id);
941 $html .= '<a href="#" class="button outline primary clear-permalink ld-ext-right">'.esc_html($label).'<span class="ld ld-spin ld-ring"></span></a>';
942 $html .= '</div>';
943 $html .= $this->get_field_description($args);
944
945 echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
946 } //end method callback_slug
947
948 /**
949 * Displays a textarea for a settings field
950 *
951 * @param array $args settings field args
952 */
953 function callback_shortcode($args)
954 {
955 $value = $args['default'];
956 $value_esc = esc_textarea($value);
957 $size = isset($args['size']) && ! is_null($args['size']) ? $args['size'] : 'regular';
958 $class = isset($args['class']) && ! is_null($args['class']) ? $args['class'] : '';
959
960 $required = isset($args['required']) ? 'required' : '';
961
962
963 $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>',
964 $size,
965 $args['section'],
966 $args['id'],
967 $value_esc,
968 $required, $class);
969
970 $html .= '<a data-target-cp="#'.$args['section'].'\\['.$args['id'].'\\]'.'" class="shortcode_demo_btn" href="#">Click to copy shortcode</a>';
971 $html .= $this->get_field_description($args);
972
973
974 $html .= '<div class="shortcode_demo_wrap">'.do_shortcode($value).'</div>';
975
976 echo $html;// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
977 }//end method callback_shortcode
978
979
980 /**
981 * Convert an array to associative if not
982 *
983 * @param $value
984 */
985 /*private function convert_associate($value){
986 if(!$this->is_associate($value) && sizeof($value) > 0){
987 $new_value = array();
988 foreach ($value as $val){
989 $new_value[$val] = ucfirst($val);
990 }
991 return $new_value;
992 }
993
994
995 return $value;
996 }*/
997
998 /**
999 * Clean label_for or id tad
1000 *
1001 * @param $str
1002 *
1003 * @return string
1004 */
1005 public function settings_clean_label_for($str)
1006 {
1007 $str = str_replace('][', '_', $str);
1008 $str = str_replace(']', '_', $str);
1009
1010 return str_replace('[', '_', $str);
1011 }//end settings_clean_label_for
1012
1013
1014 /**
1015 * check if any array is associative
1016 *
1017 * @param array $array
1018 *
1019 * @return bool
1020 */
1021 private function is_associate(array $array)
1022 {
1023 return count(array_filter(array_keys($array), 'is_string')) > 0;
1024 }
1025
1026 /**
1027 * Sanitize callback for Settings API
1028 */
1029 function sanitize_options($options)
1030 {
1031 foreach ($options as $option_slug => $option_value) {
1032 $sanitize_callback = $this->get_sanitize_callback($option_slug);
1033
1034 // If callback is set, call it
1035 if ($sanitize_callback) {
1036 $options[$option_slug] = call_user_func($sanitize_callback, $option_value);
1037 continue;
1038 }
1039 }
1040
1041 return $options;
1042 }
1043
1044 /**
1045 * Get sanitization callback for given option slug
1046 *
1047 * @param string $slug option slug
1048 *
1049 * @return mixed string or bool false
1050 */
1051 function get_sanitize_callback($slug = '')
1052 {
1053 if (empty($slug)) {
1054 return false;
1055 }
1056
1057 // Iterate over registered fields and see if we can find proper callback
1058 foreach ($this->settings_fields as $section => $options) {
1059 foreach ($options as $option) {
1060 if ($option['name'] != $slug) {
1061 continue;
1062 }
1063
1064 if (($option['type'] == 'select' && isset($option['multi']) && $option['multi']) || $option['type'] == 'multicheck') {
1065 $option['sanitize_callback'] = [$this, 'sanitize_multi_select_check'];
1066 }
1067
1068 // Return the callback name
1069 return isset($option['sanitize_callback']) && is_callable($option['sanitize_callback']) ? $option['sanitize_callback'] : false;
1070 }
1071 }
1072
1073 return false;
1074 }//end get_sanitize_callback
1075
1076 /**
1077 * Remove empty values from multi select fields (multi select and multi checkbox)
1078 *
1079 * @param $option_value
1080 *
1081 * @return array
1082 */
1083 public function sanitize_multi_select_check($option_value)
1084 {
1085 if (is_array($option_value)) {
1086 return array_filter($option_value);
1087 }
1088
1089 return $option_value;
1090 }
1091
1092 /**
1093 * Sort options based on saved values
1094 *
1095 * @param $options
1096 * @param $saved_values
1097 *
1098 * @return array|mixed
1099 */
1100 public function sort_options_by_saved_values($options, $saved_values)
1101 {
1102 // Ensure saved values is an array
1103 if ( ! is_array($saved_values)) {
1104 return $options;
1105 }
1106
1107 // Filter out any saved keys that are not in options
1108 $saved_values = array_filter($saved_values, function ($key) use ($options) {
1109 return isset($options[$key]);
1110 });
1111
1112 // Sort options based on saved values order, keeping others at the end
1113 $sorted_options = [];
1114 foreach ($saved_values as $key) {
1115 if (isset($options[$key])) {
1116 $sorted_options[$key] = $options[$key];
1117 }
1118 }
1119
1120 // Append any missing options at the end
1121 foreach ($options as $key => $value) {
1122 if ( ! isset($sorted_options[$key])) {
1123 $sorted_options[$key] = $value;
1124 }
1125 }
1126
1127 return $sorted_options;
1128 }//end method sort_options_by_saved_values
1129
1130
1131 /**
1132 * Get the value of a settings field
1133 *
1134 * @param string $option settings field name
1135 * @param string $section the section name this field belongs to
1136 * @param string $default default text if it's not found
1137 *
1138 * @return string
1139 */
1140 function get_option($option, $section, $default = '')
1141 {
1142 $options = get_option($section, []);
1143
1144 if (isset($options[$option])) {
1145 return $options[$option];
1146 }
1147
1148 return $default;
1149 }//end method get_option
1150
1151 /**
1152 * Get the value of a settings field
1153 *
1154 * @param string $option settings field name
1155 * @param string $section the section name this field belongs to
1156 * @param string $default default text if it's not found
1157 *
1158 * @return string
1159 */
1160 function get_field($option, $section, $default = '')
1161 {
1162 $options = get_option($section, []);
1163
1164 if (isset($options[$option])) {
1165 return $options[$option];
1166 }
1167
1168 return $default;
1169 }//end method get_option
1170
1171 /**
1172 * Show navigations as tab
1173 *
1174 * Shows all the settings section labels as tab
1175 */
1176 function show_navigation()
1177 {
1178 $html = '<nav class="tabs setting-tabs setting-tabs-nav mb-0">';
1179
1180 $i = 0;
1181
1182 $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">';
1183
1184 foreach ($this->settings_sections as $tab) {
1185 $active_class = ($i === 0) ? 'active' : '';
1186 $active_select = ($i === 0) ? ' selected ' : '';
1187
1188
1189 $html .= sprintf('<a data-tabid="'.esc_attr($tab['id']).'" href="#%1$s" class="%3$s" id="%1$s-tab">%2$s</a>',
1190 $tab['id'], $tab['title'], $active_class);
1191 $mobile_navs .= '<option '.esc_attr($active_select).' value="'.esc_attr($tab['id']).'">'.esc_attr($tab['title']).'</option>';
1192 $i++;
1193 }
1194
1195
1196 $mobile_navs .= '</select></div>';
1197 $html .= '</nav>';
1198
1199 echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1200 echo $mobile_navs; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1201 }//end method show_navigation
1202
1203 /**
1204 * Show the section settings forms
1205 *
1206 * This function displays every sections in a different form
1207 */
1208 function show_forms()
1209 {
1210 ?>
1211 <div id="setting-tabs-contents">
1212 <div id="global_setting_group_actions" class="mb-0">
1213 <?php do_action('cbxgooglemap_setting_group_actions_start'); ?>
1214 <a class="button outline primary global_setting_group_action global_setting_group_action_open pull-right"
1215 href="#"><?php esc_html_e('Toggle All Sections', 'cbxgooglemap'); ?></a>
1216 <?php do_action('cbxgooglemap_setting_group_actions_end'); ?>
1217 <div class="clear clearfix"></div>
1218 </div>
1219 <div class="metabox-holder">
1220 <?php
1221 $i = 0;
1222 foreach ($this->settings_sections as $form):
1223 $display_style = ($i === 0) ? '' : 'display: none;';
1224 ?>
1225 <div id="<?php echo esc_attr($form['id']); ?>" class="global_setting_group"
1226 style="<?php echo $display_style; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1227 ?>">
1228 <form method="post" action="options.php" class="cbxgooglemap_setting_form">
1229 <?php
1230 do_action('cbxgooglemap_setting_form_start', $form);
1231 do_action('cbxgooglemap_setting_form_top_'.$form['id'], $form);
1232
1233 settings_fields($form['id']);
1234 do_settings_sections($form['id']);
1235
1236 do_action('cbxgooglemap_setting_form_bottom_'.$form['id'], $form);
1237 do_action('cbxchangelog_setting_form_end', $form);
1238 ?>
1239 <div class="global_setting_submit_buttons_wrap">
1240 <?php do_action('cbxgooglemap_setting_submit_buttons_start', $form['id']); ?>
1241 <?php submit_button(esc_html__('Save Settings', 'cbxgooglemap'),
1242 'button primary submit_setting', 'submit', true,
1243 ['id' => 'submit_'.esc_attr($form['id'])]);
1244
1245
1246 $security = wp_create_nonce('cbxgooglemap_settings_nonce');
1247
1248 $settings_export_url = add_query_arg([
1249 'cbxgooglemap_settings_export' => 1,
1250 'security' => $security,
1251 'section' => $form['id']
1252 ], site_url());
1253
1254 $more_v_svg = cbxgooglemap_esc_svg(cbxgooglemap_load_svg('icon_more_v'));
1255
1256 echo '<details class="dropdown ml-10">';
1257 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
1258 echo '<div class="card card-menu card-menu-right">';
1259 echo '<ul>';
1260 echo '<li><a href="'.esc_url($settings_export_url).'" class="button outline primary submit_export_section">'.esc_attr__('Export Section',
1261 'cbxgooglemap').'</a></li>';
1262 echo '<li><a data-section="'.esc_attr($form['id']).'" href="#" class="button outline primary submit_reset_section">'.esc_attr__('Reset Section',
1263 'cbxgooglemap').'</a></li>';
1264 echo '</ul>';
1265 echo '</div>';
1266 echo '</details>';
1267 ?>
1268
1269
1270 <?php do_action('cbxgooglemap_setting_submit_buttons_end', $form['id']); ?>
1271 </div>
1272 </form>
1273 </div>
1274 <?php
1275 $i++;
1276 endforeach;
1277 ?>
1278 </div>
1279 </div>
1280 <?php
1281 }//end show_forms
1282
1283 /**
1284 * Displays a textarea for a settings field
1285 *
1286 * @param array $args
1287 * @param $value
1288 *
1289 * @return void
1290 */
1291 function callback_html($args, $value = null)
1292 {
1293 echo $this->get_field_description($args);//phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1294 } //end method callback_html
1295 }