settings_sections = $sections; return $this; } /** * Add a single section * * @param array $section */ function add_section($section) { $this->settings_sections[] = $section; return $this; } /** * Set settings fields * * @param array $fields settings fields array */ function set_fields($fields) { $this->settings_fields = $fields; return $this; } function add_field($section, $field) { $defaults = [ 'name' => '', 'label' => '', 'desc' => '', 'type' => 'text', ]; $arg = wp_parse_args($field, $defaults); $this->settings_fields[$section][] = $arg; return $this; }//end method add_field function admin_init() { //register settings sections foreach ($this->settings_sections as $section) { if (false == get_option($section['id'])) { $section_default_value = $this->getDefaultValueBySection($section['id']); add_option($section['id'], $section_default_value); } else { $section_default_value = $this->getMissingDefaultValueBySection($section['id']); update_option($section['id'], $section_default_value); } if (isset($section['desc']) && ! empty($section['desc'])) { $section['desc'] = '
'.$section['desc'].'
'; //$callback = create_function('', 'echo "' . str_replace('"', '\"', $section['desc']) . '";'); $callback = function () use ($section) { echo str_replace('"', '\"', $section['desc']); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped }; } elseif (isset($section['callback'])) { $callback = $section['callback']; } else { $callback = null; } add_settings_section($section['id'], $section['title'], $callback, $section['id']); } //register settings fields foreach ($this->settings_fields as $section => $field) { foreach ($field as $option) { $name = $option['name']; $type = isset($option['type']) ? $option['type'] : 'text'; $label = isset($option['label']) ? $option['label'] : ''; $callback = isset($option['callback']) ? $option['callback'] : [$this, 'callback_'.$type]; $label_for = $this->settings_clean_label_for("{$section}_{$option['name']}"); $args = [ 'id' => $option['name'], 'class' => isset($option['class']) ? $option['class'] : $name, 'label_for' => $label_for, 'desc' => isset($option['desc']) ? $option['desc'] : '', 'name' => $label, 'section' => $section, 'size' => isset($option['size']) ? $option['size'] : null, 'min' => isset($option['min']) ? $option['min'] : '', 'max' => isset($option['max']) ? $option['max'] : '', 'step' => isset($option['step']) ? $option['step'] : '', 'options' => isset($option['options']) ? $option['options'] : '', 'default' => isset($option['default']) ? $option['default'] : '', 'sanitize_callback' => isset($option['sanitize_callback']) ? $option['sanitize_callback'] : '', 'placeholder' => isset($option['placeholder']) ? $option['placeholder'] : '', 'type' => $type, 'optgroup' => isset($option['optgroup']) ? intval($option['optgroup']) : 0, 'multi' => isset($option['multi']) ? intval($option['multi']) : 0, 'fields' => isset($option['fields']) ? $option['fields'] : [], 'sortable' => isset($option['sortable']) ? intval($option['sortable']) : 0, 'allow_new' => isset($option['allow_new']) ? intval($option['allow_new']) : 0, //only works for repeatable 'allow_clear' => isset($option['allow_clear']) ? intval($option['allow_clear']) : 0, //only works for repeatable 'check_content' => isset($option['check_content']) ? $option['check_content'] : '', 'inline' => isset($option['inline']) ? absint($option['inline']) : 1, ]; add_settings_field("{$section}[{$name}]", $label, $callback, $section, $section, $args); } } // creates our settings in the options table foreach ($this->settings_sections as $section) { // phpcs:ignore PluginCheck.CodeAnalysis.SettingSanitization.register_settingDynamic register_setting($section['id'], $section['id'], [$this, 'sanitize_options']); } }//end method admin_init /** * Prepares default values by section * * @param $section_id * * @return array */ function getDefaultValueBySection($section_id) { $default_values = []; $fields = $this->settings_fields[$section_id]; foreach ($fields as $field) { $default_values[$field['name']] = isset($field['default']) ? $field['default'] : ''; } return $default_values; }//end getDefaultValueBySection /** * Prepares default values by section * * @param $section_id * * @return array */ function getMissingDefaultValueBySection($section_id) { $section_value = get_option($section_id); $fields = $this->settings_fields[$section_id]; foreach ($fields as $field) { if ( ! isset($section_value[$field['name']])) { $section_value[$field['name']] = isset($field['default']) ? $field['default'] : ''; } } return $section_value; }//end getMissingDefaultValueBySection /** * Get field description for display * * @param $args * * @return string */ public function get_field_description($args) { if ( ! empty($args['desc'])) { $desc = sprintf('

%s

', $args['desc']); } else { $desc = ''; } return $desc; }//end method get_field_description /** * Displays heading field using h3 * * @param array $args * * @return string */ function callback_heading($args) { $plus_svg = cbxgooglemap_esc_svg(cbxgooglemap_load_svg('icon_plus')); $minus_svg = cbxgooglemap_esc_svg(cbxgooglemap_load_svg('icon_minus')); $html = '

'.esc_html($args['name']).''.$plus_svg.''.$minus_svg.'

'; $html .= $this->get_field_description($args); echo $html;//phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped }//end method callback_heading /** * Displays sub heading field using h4 * * @param array $args * * @return void */ function callback_subheading($args) { $html = '

'.$args['name'].'

'; $html .= $this->get_field_description($args); echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped }//end method callback_subheading /** * Displays a text field for a settings field * * @param array $args * @param $value * * @return void */ function callback_text($args, $value = null) { if ($value === null) { $value = esc_attr($this->get_option($args['id'], $args['section'], $args['default'])); } $size = isset($args['size']) && ! is_null($args['size']) ? $args['size'] : 'regular'; $type = isset($args['type']) ? $args['type'] : 'text'; $html_id = "{$args['section']}_{$args['id']}"; $html_id = $this->settings_clean_label_for($html_id); $html = sprintf('', $type, $size, $args['section'], $args['id'], $value, $html_id); $html .= $this->get_field_description($args); echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped }//end callback_text /** * Displays an url field for a settings field * * @param array $args * @param null $value * * @return void */ function callback_url($args, $value = null) { $this->callback_text($args, $value); }//end method callback_url /** * Displays a number field for a settings field * * @param array $args * * @return void */ function callback_number($args, $value = null) { if ($value === null) { $value = esc_attr($this->get_option($args['id'], $args['section'], $args['default'])); } $size = isset($args['size']) && ! is_null($args['size']) ? $args['size'] : 'regular'; $type = isset($args['type']) ? $args['type'] : 'number'; $placeholder = empty($args['placeholder']) ? '' : ' placeholder="'.$args['placeholder'].'"'; $min = empty($args['min']) ? '' : ' min="'.$args['min'].'"'; $max = empty($args['max']) ? '' : ' max="'.$args['max'].'"'; $step = empty($args['max']) ? '' : ' step="'.$args['step'].'"'; $html_id = "{$args['section']}_{$args['id']}"; $html_id = $this->settings_clean_label_for($html_id); $html = sprintf('', $type, $size, $args['section'], $args['id'], $value, $placeholder, $min, $max, $step, $html_id); $html .= $this->get_field_description($args); echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped }//end method callback_number /** * Displays a multicheckbox a settings field * * @param array $args * @param $value * * @return void */ function callback_radio($args, $value = null) { if ($value === null) { $value = $this->get_option($args['id'], $args['section'], $args['default']); } $display_inline = isset($args['inline']) ? absint($args['inline']) : 1; $display_inline_class = ($display_inline) ? 'radio_fields_inline' : ''; $html = '
'; foreach ($args['options'] as $key => $label) { $html_id = "{$args['section']}_{$args['id']}_{$key}"; $html_id = $this->settings_clean_label_for($html_id); $html .= '
'; //$html .= sprintf( '', $args['section'], $args['id'], $key, checked( $value, $key, false ), $html_id ); $html .= sprintf('', $args['section'], $args['id'], $key, checked($value, $key, false), $html_id); $html .= sprintf('', $label); $html .= '
'; } $html .= $this->get_field_description($args); $html .= '
'; echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped }//end method callback_radio /** * Displays a checkbox for a settings field * * @param array $args * @param $value * * @return void */ function callback_checkbox($args, $value = null) { if ($value === null) { $value = esc_attr($this->get_option($args['id'], $args['section'], $args['default'])); } $html_id = "{$args['section']}_{$args['id']}"; $html_id = $this->settings_clean_label_for($html_id); $html = '
'; $html .= sprintf('', $args['section'], $args['id']); $html .= sprintf('', $args['section'], $args['id'], checked($value, 'on', false), $html_id); $html .= sprintf('', $args['desc']); $html .= '
'; echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped }//end method callback_checkbox /** * Displays a multicheckbox settings field * * @param array $args * @param $value * * @return void */ function callback_multicheck($args, $value = null) { $sortable = isset($args['sortable']) ? intval($args['sortable']) : 0; if ($value === null) { $value = $this->get_option($args['id'], $args['section'], $args['default']); } if ( ! is_array($value)) { $value = []; } $options = $args['options'];//this can be regular array or associative array $value = array_values($value); $display_inline = isset($args['inline']) ? absint($args['inline']) : 1; $display_inline_class = ''; if ($sortable) { $display_inline = 0; } $display_inline_class .= ($display_inline) ? 'checkbox_fields_inline' : ''; $sortable_class = ($sortable) ? 'checkbox_fields_sortable' : ''; $html = '

'.esc_html__('Check All', 'cbxgooglemap').''.esc_html__('Uncheck All', 'cbxgooglemap').'

'; $html .= '
'; if ($sortable) { $options = $this->sort_options_by_saved_values($options, $value); } foreach ($options as $key => $label) { $checked = in_array($key, $value) ? ' checked="checked" ' : ''; $html_id = "{$args['section']}_{$args['id']}_{$key}"; $html_id = $this->settings_clean_label_for($html_id); $html .= '
'; if ($sortable) { $html .= ''; } $html .= sprintf('', $args['section'], $args['id'], $key); $html .= sprintf('', $args['section'], $args['id'], $key, $checked, $html_id); $html .= sprintf('', $label); $html .= '
'; } $html .= $this->get_field_description($args); $html .= '
'; echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped }//end method callback_multicheck /** * Displays a select box for a settings field * * @param $args * * @return void */ function callback_select($args) { $value = $this->get_option($args['id'], $args['section'], $args['default']); $multi = isset($args['multi']) ? intval($args['multi']) : 0; $multi_name = ($multi) ? '[]' : ''; $multi_attr = ($multi) ? 'multiple' : ''; if ($multi && ! is_array($value)) { $value = []; } /*if ( ! is_array( $value ) ) { $value = []; }*/ $size = isset($args['size']) && ! is_null($args['size']) ? $args['size'] : 'regular selecttwo-select'; if ($args['placeholder'] == '') { $args['placeholder'] = esc_html__('Please Select', 'cbxgooglemap'); } $html = sprintf('', $args['section'], $args['id']); $html .= sprintf('
'; $html .= $this->get_field_description($args); echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped }//end method callback_select /** * Displays a select box for a settings field * * @param $args * * @return void */ function callback_page($args) { $edit_svg = cbxgooglemap_esc_svg(cbxgooglemap_load_svg('icon_edit')); $external_svg = cbxgooglemap_esc_svg(cbxgooglemap_load_svg('icon_external')); $value = absint($this->get_option($args['id'], $args['section'], intval($args['default']))); $size = isset($args['size']) && ! is_null($args['size']) ? $args['size'] : 'regular selecttwo-select'; $check_content = isset($args['check_content']) && ! is_null($args['check_content']) ? $args['check_content'] : ''; $allow_clear = isset($args['allow_clear']) ? intval($args['allow_clear']) : 0; $page_content = ''; $page_shortcode_note = ''; $shortcode_found_class = ''; $html = '
'; $page_html = '
'; if ($value > 0) { if ($check_content != '') { $page = get_post($value); $page_content = $page->post_content; if (has_shortcode($page_content, $check_content)) { $shortcode_found_class = 'description_note_on'; /* translators: %s: content */ $page_shortcode_note = sprintf(esc_html__('This page has shortcode %s', 'cbxgooglemap'), $check_content); } else { $shortcode_found_class = 'description_note_off'; /* translators: %s: content */ $page_shortcode_note = sprintf(esc_html__('This page doesn\'t have shortcode %s', 'cbxgooglemap'), $check_content); } } //edit if (current_user_can('edit_post', $value)) { $page_html .= ''.$edit_svg.''; } //view $page_html .= ''.$external_svg.''; } $page_html .= '
'; if ($args['placeholder'] == '') { $placeholder = $args['placeholder'] = esc_html__('Please Select', 'cbxgooglemap'); } else { $placeholder = esc_attr($args['placeholder']); } $html .= sprintf('', $args['section'], $args['id']); $html .= sprintf('
'.$page_html; $html .= '
'; //.setting_pages_actions_wrapper if ($page_shortcode_note != '') { $html .= '

'.$page_shortcode_note.'

'; } $html .= $this->get_field_description($args); echo $html;//phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped }//end method callback_page /** * Displays a textarea for a settings field * * @param array $args * @param $value * * @return void */ function callback_textarea($args, $value = null) { if ($value === null) { $value = esc_textarea($this->get_option($args['id'], $args['section'], $args['default'])); } $size = isset($args['size']) && ! is_null($args['size']) ? $args['size'] : 'regular'; $html_id = "{$args['section']}_{$args['id']}"; $html_id = $this->settings_clean_label_for($html_id); $html = sprintf('', $size, $args['section'], $args['id'], $value, $html_id); $html .= $this->get_field_description($args); echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped }//end method callback_textarea /** * Displays a rich text textarea for a settings field * * @param array $args * @param $value * * @return void */ function callback_wysiwyg($args, $value = null) { if ($value === null) { $value = $this->get_option($args['id'], $args['section'], $args['default']); } $size = isset($args['size']) && ! is_null($args['size']) ? $args['size'] : '500px'; echo '
'; $html_id = "{$args['section']}_{$args['id']}"; $html_id = $this->settings_clean_label_for($html_id); $editor_settings = [ 'teeny' => true, 'textarea_name' => $args['section'].'['.$args['id'].']', 'textarea_rows' => 10 ]; if (isset($args['options']) && is_array($args['options'])) { $editor_settings = array_merge($editor_settings, $args['options']); } //wp_editor( $value, $args['section'] . '-' . $args['id'], $editor_settings ); wp_editor($value, $html_id, $editor_settings); echo '
'; echo $this->get_field_description($args); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped }//end method callback_wysiwyg /** * Displays a file upload field for a settings field * * @param array $args settings field args */ function callback_file($args) { $value = esc_attr($this->get_option($args['id'], $args['section'], $args['default'])); $size = isset($args['size']) && ! is_null($args['size']) ? $args['size'] : 'regular'; $id = $args['section'].'['.$args['id'].']'; $label = isset($args['options']['button_label']) ? $args['options']['button_label'] : esc_html__('Choose File', 'cbxgooglemap'); $html = '
'; $html .= sprintf('', $size, $args['section'], $args['id'], $value); $icon_extra_class = ''; $marker_icon = ''; $trash_extra_class = ''; if ($value === '') { $icon_extra_class = 'cbxchota-setting_marker_hide'; $file_picked_class = 'cbxchota-setting_left_space'; $trash_extra_class = 'cbxchota-setting_trash_hide'; } else { $marker_icon = ' background-image: url(\''.esc_url($value).'\') ;'; $file_picked_class = 'cbxchota-setting_filepicked'; } $html .= ''; $html .= ''; $html .= ''; $html .= '
'; $html .= $this->get_field_description($args); echo $html;// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped }//end method callback_file /** * Displays a color picker field for a settings field * * @param array $args * @param $value * * @return void */ function callback_color($args, $value = null) { if ($value === null) { $value = esc_attr($this->get_option($args['id'], $args['section'], $args['default'])); } $size = isset($args['size']) && ! is_null($args['size']) ? $args['size'] : 'regular'; $html_id = "{$args['section']}_{$args['id']}"; $html_id = $this->settings_clean_label_for($html_id); $choose_color = esc_html__('Choose Color', 'cbxgooglemap'); $html = '
'; $html .= sprintf('%7$s', $size, $args['section'], $args['id'], $value, $args['default'], $html_id, $choose_color); $html .= '
'; $html .= $this->get_field_description($args); echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped }//end callback_color /** * Displays a password field for a settings field * * @param array $args * * @return void */ function callback_password($args) { $value = esc_attr($this->get_option($args['id'], $args['section'], $args['default'])); $size = isset($args['size']) && ! is_null($args['size']) ? $args['size'] : 'regular'; $html = sprintf('', $size, $args['section'], $args['id'], $value); $html .= $this->get_field_description($args); echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped }//end method callback_password /** * Displays a email field for a settings field * * @param array $args settings field args */ function callback_email($args) { $value = esc_attr($this->get_option($args['id'], $args['section'], $args['default'])); $size = isset($args['size']) && ! is_null($args['size']) ? $args['size'] : 'regular'; $type = isset($args['type']) ? $args['type'] : 'text'; $html_id = "{$args['section']}_{$args['id']}"; $html_id = $this->settings_clean_label_for($html_id); $html = sprintf('', $type, $size, $args['section'], $args['id'], $value, $html_id); $html .= $this->get_field_description($args); echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped }//end method callback_email /** * Displays custom file extension checker checkbox for a settings field * * @param array $args settings field args */ function callback_file_extensions_checker($args) { $stored_ext_arr = $this->get_option($args['id'], $args['section'], $args['default']); $image_ext_arr = CBXGooglemapHelper::getImageExts(); $html = sprintf('', $args['section'], $args['id']); $html .= '
'; foreach ($image_ext_arr as $index => $extension) { // checkbox html $html .= '
'; $html .= sprintf(' ', $args['section'], $args['id'], $index, ucfirst($extension), checked((is_array($stored_ext_arr) && in_array($extension, $stored_ext_arr)), '1', false) ); $html .= '
'; } $html .= '
'; echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped }//end method callback_file_extensions_checker /** * Displays a text field for a settings field * * @param array $args settings field args */ function callback_slug($args) { $value = esc_attr($this->get_field($args['id'], $args['section'], $args['default'])); $size = isset($args['size']) && ! is_null($args['size']) ? $args['size'] : 'regular'; //$id = $args['section'] . '[' . $args['id'] . ']'; $html_id = "{$args['section']}_{$args['id']}"; $html_id = $this->settings_clean_label_for($html_id); $label = isset($args['options']['button_label']) ? $args['options']['button_label'] : esc_html__('Clear Permalinks', 'cbxgooglemap'); $html = ''; $html .= $this->get_field_description($args); echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } //end method callback_slug /** * Displays a textarea for a settings field * * @param array $args settings field args */ function callback_shortcode($args) { $value = $args['default']; $value_esc = esc_textarea($value); $size = isset($args['size']) && ! is_null($args['size']) ? $args['size'] : 'regular'; $class = isset($args['class']) && ! is_null($args['class']) ? $args['class'] : ''; $required = isset($args['required']) ? 'required' : ''; $html = sprintf('', $size, $args['section'], $args['id'], $value_esc, $required, $class); $html .= 'Click to copy shortcode'; $html .= $this->get_field_description($args); $html .= '
'.do_shortcode($value).'
'; echo $html;// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped }//end method callback_shortcode /** * Convert an array to associative if not * * @param $value */ /*private function convert_associate($value){ if(!$this->is_associate($value) && sizeof($value) > 0){ $new_value = array(); foreach ($value as $val){ $new_value[$val] = ucfirst($val); } return $new_value; } return $value; }*/ /** * Clean label_for or id tad * * @param $str * * @return string */ public function settings_clean_label_for($str) { $str = str_replace('][', '_', $str); $str = str_replace(']', '_', $str); return str_replace('[', '_', $str); }//end settings_clean_label_for /** * check if any array is associative * * @param array $array * * @return bool */ private function is_associate(array $array) { return count(array_filter(array_keys($array), 'is_string')) > 0; } /** * Sanitize callback for Settings API */ function sanitize_options($options) { foreach ($options as $option_slug => $option_value) { $sanitize_callback = $this->get_sanitize_callback($option_slug); // If callback is set, call it if ($sanitize_callback) { $options[$option_slug] = call_user_func($sanitize_callback, $option_value); continue; } } return $options; } /** * Get sanitization callback for given option slug * * @param string $slug option slug * * @return mixed string or bool false */ function get_sanitize_callback($slug = '') { if (empty($slug)) { return false; } // Iterate over registered fields and see if we can find proper callback foreach ($this->settings_fields as $section => $options) { foreach ($options as $option) { if ($option['name'] != $slug) { continue; } if (($option['type'] == 'select' && isset($option['multi']) && $option['multi']) || $option['type'] == 'multicheck') { $option['sanitize_callback'] = [$this, 'sanitize_multi_select_check']; } // Return the callback name return isset($option['sanitize_callback']) && is_callable($option['sanitize_callback']) ? $option['sanitize_callback'] : false; } } return false; }//end get_sanitize_callback /** * Remove empty values from multi select fields (multi select and multi checkbox) * * @param $option_value * * @return array */ public function sanitize_multi_select_check($option_value) { if (is_array($option_value)) { return array_filter($option_value); } return $option_value; } /** * Sort options based on saved values * * @param $options * @param $saved_values * * @return array|mixed */ public function sort_options_by_saved_values($options, $saved_values) { // Ensure saved values is an array if ( ! is_array($saved_values)) { return $options; } // Filter out any saved keys that are not in options $saved_values = array_filter($saved_values, function ($key) use ($options) { return isset($options[$key]); }); // Sort options based on saved values order, keeping others at the end $sorted_options = []; foreach ($saved_values as $key) { if (isset($options[$key])) { $sorted_options[$key] = $options[$key]; } } // Append any missing options at the end foreach ($options as $key => $value) { if ( ! isset($sorted_options[$key])) { $sorted_options[$key] = $value; } } return $sorted_options; }//end method sort_options_by_saved_values /** * Get the value of a settings field * * @param string $option settings field name * @param string $section the section name this field belongs to * @param string $default default text if it's not found * * @return string */ function get_option($option, $section, $default = '') { $options = get_option($section, []); if (isset($options[$option])) { return $options[$option]; } return $default; }//end method get_option /** * Get the value of a settings field * * @param string $option settings field name * @param string $section the section name this field belongs to * @param string $default default text if it's not found * * @return string */ function get_field($option, $section, $default = '') { $options = get_option($section, []); if (isset($options[$option])) { return $options[$option]; } return $default; }//end method get_option /** * Show navigations as tab * * Shows all the settings section labels as tab */ function show_navigation() { $html = ''; echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped echo $mobile_navs; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped }//end method show_navigation /** * Show the section settings forms * * This function displays every sections in a different form */ function show_forms() { ?>
settings_sections as $form): $display_style = ($i === 0) ? '' : 'display: none;'; ?>
'submit_'.esc_attr($form['id'])]); $security = wp_create_nonce('cbxgooglemap_settings_nonce'); $settings_export_url = add_query_arg([ 'cbxgooglemap_settings_export' => 1, 'security' => $security, 'section' => $form['id'] ], site_url()); $more_v_svg = cbxgooglemap_esc_svg(cbxgooglemap_load_svg('icon_more_v')); echo ''; ?>
get_field_description($args);//phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } //end method callback_html }