<?php
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
class Rusnetim_Options {
private static $option_name = 'rusnetim_options';
private static $defaults = [];
private static $defaults_backup = [];
public static function init() {
self::$defaults = [
'center_map_option' => '53.334554,83.786980',
'zoom_map_option' => '12',
'type_map_option' => 'yandex#map',
'height_map_option' => '22rem',
'controls_map_option' => '',
'wheelzoom_map_option' => 'off',
'mobiledrag_map_option' => 'off',
'type_icon_option' => 'islands#dotIcon',
'color_icon_option' => '#1e98ff',
'apikey_map_option' => '',
'reset_maps_option' => 'off',
'cluster_map_option' => 'off',
'cluster_grid_option' => '64',
'cluster_color_option' => '#1e98ff',
'custom_icon_option' => '',
'custom_icon_width_option' => '',
'custom_icon_height_option' => '',
'info_panel_side' => 'right',
'info_panel_width' => '300px',
'info_panel_title_position' => 'below',
'info_title_tag' => 'h3',
'info_title_font_size' => '',
'info_title_color' => '',
'info_panel_bg_color' => '#ffffff',
'cat_filter_container_justify' => 'flex-start',
'cat_filter_button_tag' => 'button',
'cat_filter_button_font_size' => '',
'cat_filter_button_color' => '',
'cat_filter_button_bg_color' => '',
'cat_filter_button_border' => '',
'cat_filter_button_box_shadow' => '',
'cat_filter_button_padding' => '6px 12px',
'cat_filter_button_border_radius' => '4px',
'cat_filter_button_active_color' => '',
'cat_filter_button_active_bg_color'=> '',
'cat_filter_button_active_border' => '',
];
self::$defaults = apply_filters( 'rusnetim_default_options', self::$defaults );
self::$defaults_backup = self::$defaults;
}
public static function get_option_name() {
return self::$option_name;
}
public static function get( $key, $default = null ) {
$options = get_option( self::$option_name, [] );
if ( isset( $options[ $key ] ) ) {
return $options[ $key ];
}
return $default ?? ( self::$defaults[ $key ] ?? '' );
}
public static function get_all() {
$saved = get_option( self::$option_name, [] );
$all = array_merge( self::$defaults, $saved );
if ( isset( $all['controls_map_option'] ) ) {
$fixpos = strripos( $all['controls_map_option'], '111' );
if ( is_int( $fixpos ) ) {
$fixpattern = array('111;', '111');
$all['controls_map_option'] = str_replace( $fixpattern, '', $all['controls_map_option'] );
self::update_all( $all );
}
}
return $all;
}
public static function update_all( $options ) {
update_option( self::$option_name, $options );
}
public static function sanitize( $input ) {
$old_options = get_option( self::$option_name, [] );
$sanitized = $old_options;
if ( isset( $input['center_map_option'] ) ) {
$sanitized['center_map_option'] = self::sanitize_coords( $input['center_map_option'] );
}
if ( isset( $input['zoom_map_option'] ) ) {
$sanitized['zoom_map_option'] = (string) self::sanitize_zoom( $input['zoom_map_option'] );
}
if ( isset( $input['type_map_option'] ) ) {
$sanitized['type_map_option'] = self::sanitize_map_type( $input['type_map_option'] );
}
if ( isset( $input['height_map_option'] ) ) {
$height = sanitize_text_field( $input['height_map_option'] );
if ( preg_match( '/^\d+(\.\d+)?(rem|em|px|vh)$/', $height ) ) {
$sanitized['height_map_option'] = $height;
} else {
$sanitized['height_map_option'] = '22rem';
add_settings_error( 'rusnetim_options', 'invalid_height', __( 'Map height must be specified with units: rem, em, px or vh (e.g., 400px, 30rem, 50vh). Default 22rem used.', 'rusnet-interactive-map' ), 'warning' );
}
}
if ( isset( $input['info_panel_side'] ) ) {
$side = sanitize_text_field( $input['info_panel_side'] );
$allowed_sides = apply_filters( 'rusnetim_allowed_info_panel_sides', [ 'right', 'left' ] );
if ( in_array( $side, $allowed_sides, true ) ) {
$sanitized['info_panel_side'] = $side;
} else {
$sanitized['info_panel_side'] = 'right';
}
}
if ( isset( $input['info_panel_width'] ) ) {
$width = sanitize_text_field( $input['info_panel_width'] );
if ( preg_match( '/^\d+(\.\d+)?(px|%|em|rem|vw|vh)$/', $width ) ) {
$sanitized['info_panel_width'] = $width;
} else {
$sanitized['info_panel_width'] = '300px';
add_settings_error(
'rusnetim_options',
'invalid_info_width',
__( 'Info panel width must be specified with units: px, %, em, rem, vw, vh (e.g., 300px, 50%, 20rem). Default 300px used.', 'rusnet-interactive-map' ),
'warning'
);
}
}
if ( isset( $input['info_panel_title_position'] ) ) {
$pos = sanitize_text_field( $input['info_panel_title_position'] );
if ( in_array( $pos, [ 'above', 'below' ] ) ) {
$sanitized['info_panel_title_position'] = $pos;
} else {
$sanitized['info_panel_title_position'] = 'below';
}
}
if ( isset( $input['info_title_tag'] ) ) {
$tag = sanitize_text_field( $input['info_title_tag'] );
$allowed_tags = [ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'div', 'span', 'p' ];
$sanitized['info_title_tag'] = in_array( $tag, $allowed_tags, true ) ? $tag : 'h3';
}
if ( isset( $input['info_title_font_size'] ) ) {
$size = sanitize_text_field( $input['info_title_font_size'] );
if ( preg_match( '/^\d+(\.\d+)?(px|rem|em|%|vh|vw|pt|pc)$/', $size ) ) {
$sanitized['info_title_font_size'] = $size;
} else {
$sanitized['info_title_font_size'] = '';
}
}
if ( isset( $input['info_title_color'] ) ) {
$color = sanitize_hex_color( $input['info_title_color'] );
$sanitized['info_title_color'] = $color ?: '';
}
if ( isset( $input['info_panel_bg_color'] ) ) {
$color = sanitize_hex_color( $input['info_panel_bg_color'] );
$sanitized['info_panel_bg_color'] = $color ?: '#ffffff';
}
if ( isset( $input['cat_filter_container_justify'] ) ) {
$valid = [ 'flex-start', 'center', 'flex-end', 'space-between', 'space-around', 'space-evenly' ];
$sanitized['cat_filter_container_justify'] = in_array( $input['cat_filter_container_justify'], $valid, true ) ? $input['cat_filter_container_justify'] : 'flex-start';
}
if ( isset( $input['cat_filter_button_tag'] ) ) {
$valid = [ 'button', 'a', 'div', 'span' ];
$sanitized['cat_filter_button_tag'] = in_array( $input['cat_filter_button_tag'], $valid, true ) ? $input['cat_filter_button_tag'] : 'button';
}
if ( isset( $input['cat_filter_button_font_size'] ) ) {
$size = sanitize_text_field( $input['cat_filter_button_font_size'] );
if ( preg_match( '/^\d+(\.\d+)?(px|rem|em|%|vh|vw|pt|pc)$/', $size ) ) {
$sanitized['cat_filter_button_font_size'] = $size;
} else {
$sanitized['cat_filter_button_font_size'] = '';
}
}
if ( isset( $input['cat_filter_button_color'] ) ) {
$color = sanitize_hex_color( $input['cat_filter_button_color'] );
$sanitized['cat_filter_button_color'] = $color ?: '';
}
if ( isset( $input['cat_filter_button_bg_color'] ) ) {
$color = sanitize_hex_color( $input['cat_filter_button_bg_color'] );
$sanitized['cat_filter_button_bg_color'] = $color ?: '';
}
if ( isset( $input['cat_filter_button_border'] ) ) {
$border = sanitize_text_field( $input['cat_filter_button_border'] );
$sanitized['cat_filter_button_border'] = $border;
}
if ( isset( $input['cat_filter_button_box_shadow'] ) ) {
$shadow = sanitize_text_field( $input['cat_filter_button_box_shadow'] );
$sanitized['cat_filter_button_box_shadow'] = $shadow;
}
if ( isset( $input['cat_filter_button_padding'] ) ) {
$padding = sanitize_text_field( $input['cat_filter_button_padding'] );
if ( preg_match( '/^(\d+(\.\d+)?(px|em|rem|%)?\s*){1,4}$/', $padding ) ) {
$sanitized['cat_filter_button_padding'] = $padding;
} else {
$sanitized['cat_filter_button_padding'] = '6px 12px';
}
}
if ( isset( $input['cat_filter_button_border_radius'] ) ) {
$radius = sanitize_text_field( $input['cat_filter_button_border_radius'] );
if ( preg_match( '/^\d+(\.\d+)?(px|%|em|rem)?$/', $radius ) ) {
$sanitized['cat_filter_button_border_radius'] = $radius;
} else {
$sanitized['cat_filter_button_border_radius'] = '4px';
}
}
if ( isset( $input['cat_filter_button_active_color'] ) ) {
$color = sanitize_hex_color( $input['cat_filter_button_active_color'] );
$sanitized['cat_filter_button_active_color'] = $color ?: '';
}
if ( isset( $input['cat_filter_button_active_bg_color'] ) ) {
$color = sanitize_hex_color( $input['cat_filter_button_active_bg_color'] );
$sanitized['cat_filter_button_active_bg_color'] = $color ?: '';
}
if ( isset( $input['cat_filter_button_active_border'] ) ) {
$border = sanitize_text_field( $input['cat_filter_button_active_border'] );
$sanitized['cat_filter_button_active_border'] = $border;
}
if ( isset( $input['controls_map_option'] ) ) {
$allowed_controls = array(
'fullscreenControl', 'geolocationControl', 'routeEditor', 'rulerControl',
'searchControl', 'trafficControl', 'typeSelector', 'zoomControl',
'routeButtonControl', 'routePanelControl', 'smallMapDefaultSet',
'mediumMapDefaultSet', 'largeMapDefaultSet', 'default',
);
$controls_array = array_map( 'trim', explode( ';', $input['controls_map_option'] ) );
$valid_controls = array();
foreach ( $controls_array as $control ) {
$control = sanitize_text_field( $control );
if ( in_array( $control, $allowed_controls, true ) ) {
$valid_controls[] = $control;
}
}
$sanitized['controls_map_option'] = implode( ';', $valid_controls );
}
$checkbox_fields = [
'wheelzoom_map_option',
'mobiledrag_map_option',
'cluster_map_option',
'reset_maps_option',
];
foreach ( $checkbox_fields as $field ) {
if ( isset( $input[ $field ] ) ) {
$sanitized[ $field ] = ( $input[ $field ] === 'on' ) ? 'on' : 'off';
}
}
if ( isset( $input['cluster_grid_option'] ) ) {
$grid = intval( $input['cluster_grid_option'] );
$sanitized['cluster_grid_option'] = ( $grid >= 2 && $grid <= 512 ) ? (string) $grid : '64';
}
if ( isset( $input['cluster_color_option'] ) ) {
$color = sanitize_hex_color( $input['cluster_color_option'] );
$sanitized['cluster_color_option'] = $color ? $color : '#1e98ff';
}
if ( isset( $input['type_icon_option'] ) ) {
$icon = sanitize_text_field( $input['type_icon_option'] );
if ( preg_match( '/^[a-zA-Z0-9#_\-]+$/', $icon ) || filter_var( $icon, FILTER_VALIDATE_URL ) ) {
$sanitized['type_icon_option'] = $icon;
} else {
$sanitized['type_icon_option'] = 'islands#dotIcon';
}
}
if ( isset( $input['color_icon_option'] ) ) {
$color = sanitize_hex_color( $input['color_icon_option'] );
$sanitized['color_icon_option'] = $color ? $color : '#1e98ff';
}
if ( isset( $input['custom_icon_option'] ) ) {
$custom = sanitize_text_field( $input['custom_icon_option'] );
if ( is_numeric( $custom ) || filter_var( $custom, FILTER_VALIDATE_URL ) ) {
$sanitized['custom_icon_option'] = $custom;
} else {
$sanitized['custom_icon_option'] = '';
}
}
if ( isset( $input['custom_icon_width_option'] ) ) {
$w = intval( $input['custom_icon_width_option'] );
$sanitized['custom_icon_width_option'] = $w > 0 ? $w : '';
}
if ( isset( $input['custom_icon_height_option'] ) ) {
$h = intval( $input['custom_icon_height_option'] );
$sanitized['custom_icon_height_option'] = $h > 0 ? $h : '';
}
if ( isset( $input['apikey_map_option'] ) ) {
$apikey = sanitize_text_field( $input['apikey_map_option'] );
if ( preg_match( '/^[a-zA-Z0-9\-_]*$/', $apikey ) ) {
$sanitized['apikey_map_option'] = $apikey;
} else {
$sanitized['apikey_map_option'] = '';
}
}
$sanitized = apply_filters( 'rusnetim_sanitize_options', $sanitized, $input );
return $sanitized;
}
public static function sanitize_coords( $coord ) {
$sanitized = preg_replace( '/[^0-9.,\s\-]/', '', $coord );
if ( preg_match( '/^-?\d+\.?\d*\s*,\s*-?\d+\.?\d*$/', trim( $sanitized ) ) ) {
return trim( $sanitized );
}
return '55.7558, 37.6173';
}
public static function sanitize_zoom( $zoom ) {
$zoom_int = intval( $zoom );
if ( $zoom_int < 0 ) return 0;
if ( $zoom_int > 21 ) return 21;
return $zoom_int;
}
public static function sanitize_map_type( $type ) {
$type_map = array(
'map' => 'yandex#map',
'satellite' => 'yandex#satellite',
'hybrid' => 'yandex#hybrid',
'yandex#map' => 'yandex#map',
'yandex#satellite' => 'yandex#satellite',
'yandex#hybrid' => 'yandex#hybrid',
);
$type = sanitize_text_field( $type );
return $type_map[ $type ] ?? 'yandex#map';
}
public static function sanitize_controls( $controls ) {
$allowed_controls = array(
'fullscreenControl', 'geolocationControl', 'routeEditor', 'rulerControl',
'searchControl', 'trafficControl', 'typeSelector', 'zoomControl',
'routeButtonControl', 'routePanelControl', 'smallMapDefaultSet',
'mediumMapDefaultSet', 'largeMapDefaultSet', 'default',
);
$controls_array = array_map( 'trim', explode( ';', $controls ) );
$sanitized = array();
foreach ( $controls_array as $control ) {
$control = sanitize_text_field( $control );
if ( in_array( $control, $allowed_controls, true ) ) {
$sanitized[] = $control;
}
}
return $sanitized;
}
public static function sanitize_apikey( $key ) {
$key = sanitize_text_field( $key );
return preg_match( '/^[a-zA-Z0-9\-_]*$/', $key ) ? $key : '';
}
public static function sanitize_locale( $locale ) {
return preg_match( '/^[a-z]{2}_[A-Z]{2}$/', $locale ) ? $locale : 'en_US';
}
}