array( $this, 'sanitize_settings' ), ) ); } /** * Sanitizes the settings array on save. * * @param mixed $input Raw input from the settings form. * @return array Sanitized settings. */ public function sanitize_settings( $input ): array { if ( ! is_array( $input ) ) { return self::get_defaults(); } $defaults = self::get_defaults(); $clean = array(); $clean['default_zoom'] = isset( $input['default_zoom'] ) ? max( 10, min( 200, (int) $input['default_zoom'] ) ) : $defaults['default_zoom']; $clean['autofit_threshold'] = isset( $input['autofit_threshold'] ) ? max( 0, min( 500, (int) $input['autofit_threshold'] ) ) : $defaults['autofit_threshold']; $clean['max_code_lines'] = isset( $input['max_code_lines'] ) ? max( 5, min( 500, (int) $input['max_code_lines'] ) ) : $defaults['max_code_lines']; $clean['allow_download'] = ! empty( $input['allow_download'] ); $clean['download_label'] = isset( $input['download_label'] ) ? sanitize_text_field( wp_unslash( $input['download_label'] ) ) : $defaults['download_label']; $clean['default_mode'] = in_array( $input['default_mode'] ?? '', array( 'visual', 'info', 'compact' ), true ) ? $input['default_mode'] : $defaults['default_mode']; $clean['show_infobox_default'] = ! empty( $input['show_infobox_default'] ); $clean['show_title_default'] = ! empty( $input['show_title_default'] ); $clean['schema_howto'] = ! empty( $input['schema_howto'] ); $clean['related_workflows'] = ! empty( $input['related_workflows'] ); $clean['view_counting'] = ! empty( $input['view_counting'] ); $clean['allow_share'] = ! empty( $input['allow_share'] ); $clean['allow_embed'] = ! empty( $input['allow_embed'] ); $clean['allow_get_json'] = ! empty( $input['allow_get_json'] ); $allowed_themes = \BreznFlow\Features\ThemeRegistry::get_theme_ids(); $clean['default_theme'] = in_array( $input['default_theme'] ?? '', $allowed_themes, true ) ? $input['default_theme'] : $defaults['default_theme']; // Renderer colors — validate hex format. $color_keys = array( 'trigger', 'action', 'logic', 'transform', 'database', 'ai' ); $clean['renderer_colors'] = array(); foreach ( $color_keys as $key ) { $raw_color = isset( $input['renderer_colors'][ $key ] ) ? sanitize_text_field( wp_unslash( $input['renderer_colors'][ $key ] ) ) : $defaults['renderer_colors'][ $key ]; $clean['renderer_colors'][ $key ] = preg_match( '/^#[0-9a-fA-F]{6}$/', $raw_color ) ? $raw_color : $defaults['renderer_colors'][ $key ]; } return $clean; } /** * Returns default settings. * * @return array */ public static function get_defaults(): array { return array( 'default_zoom' => 100, 'autofit_threshold' => 30, 'max_code_lines' => 50, 'allow_download' => false, 'download_label' => __( 'Download JSON', 'breznflow' ), 'default_mode' => 'visual', 'show_infobox_default' => true, 'show_title_default' => true, 'schema_howto' => false, 'related_workflows' => true, 'view_counting' => true, 'allow_share' => true, 'allow_embed' => false, 'allow_get_json' => false, 'default_theme' => 'dark', 'renderer_colors' => array( 'trigger' => '#ff6b6b', 'action' => '#4ecdc4', 'logic' => '#f39c12', 'transform' => '#26c6da', 'database' => '#4479a1', 'ai' => '#7c3aed', ), ); } }