'; echo '

'; echo ''; echo ''; echo esc_html__( '4WP Weather', '4wp-weather' ); echo ''; echo '

'; echo '
'; echo ''; } /** * Allowed tags for the static admin heading SVG. * * @return array> */ private static function weather_heading_svg_allowed_html(): array { return array( 'svg' => array( 'xmlns' => true, 'viewbox' => true, 'width' => true, 'height' => true, 'fill' => true, 'focusable' => true, 'aria-hidden' => true, ), 'path' => array( 'd' => true, 'fill' => true, 'stroke' => true, 'stroke-width' => true, 'stroke-linecap' => true, 'stroke-linejoin' => true, ), ); } /** * Inline weather icon for the settings screen heading (stroke uses currentColor for admin theme). * * @return string SVG markup. */ private static function weather_heading_svg(): string { return ''; } /** * Scripts and styles only on our screen. * * @param string $hook_suffix Current admin page. */ public function enqueue_admin_assets( string $hook_suffix ): void { if ( 'toplevel_page_forwp-weather' !== $hook_suffix ) { return; } if ( ! current_user_can( 'manage_options' ) ) { return; } $asset_file = FORWP_WEATHER_PATH . 'build/admin/index.asset.php'; if ( ! is_readable( $asset_file ) ) { return; } $asset = include $asset_file; wp_enqueue_style( 'wp-components' ); $style_path = FORWP_WEATHER_PATH . 'build/admin/style-index.css'; if ( is_readable( $style_path ) ) { wp_enqueue_style( 'forwp-weather-admin', FORWP_WEATHER_URL . 'build/admin/style-index.css', array( 'wp-components' ), $asset['version'] ); } wp_enqueue_script( 'forwp-weather-admin', FORWP_WEATHER_URL . 'build/admin/index.js', $asset['dependencies'], $asset['version'], true ); wp_set_script_translations( 'forwp-weather-admin', '4wp-weather', FORWP_WEATHER_PATH . 'languages' ); wp_localize_script( 'forwp-weather-admin', 'forwpWeatherAdmin', array( 'restRoot' => esc_url_raw( rest_url() ), 'nonce' => wp_create_nonce( 'wp_rest' ), ) ); } /** * Sanitize API key input. * * @param mixed $value Raw value. */ public function sanitize_api_key( $value ): string { $value = is_string( $value ) ? $value : ''; return sanitize_text_field( trim( $value ) ); } /** * Stored API key for the active credential provider. * * @return string */ public function get_api_key(): string { $key = get_option( self::OPTION_KEY, '' ); return is_string( $key ) ? $key : ''; } /** * Slug of the provider that receives the stored API key. * * @return string */ public function get_credential_provider(): string { $slug = get_option( self::CREDENTIAL_PROVIDER_OPTION, '' ); $slug = is_string( $slug ) ? sanitize_key( $slug ) : ''; if ( '' === $slug || ! in_array( $slug, Provider_Registry::implemented_slugs(), true ) ) { return \ForWP\Weather\Providers\OpenWeatherMap_Provider::SLUG; } return $slug; } /** * Saved preview latitude for admin live preview (optional). */ public function get_preview_latitude_saved(): string { $raw = get_option( self::PREVIEW_LAT_OPTION, '' ); if ( is_numeric( $raw ) ) { return (string) $raw; } return ''; } /** * Saved preview longitude for admin live preview (optional). */ public function get_preview_longitude_saved(): string { $raw = get_option( self::PREVIEW_LON_OPTION, '' ); if ( is_numeric( $raw ) ) { return (string) $raw; } return ''; } /** * Coordinates used for admin preview (saved pair or filter default). * * @return array{lat: float, lon: float} */ public function get_preview_coordinates(): array { $lat_raw = get_option( self::PREVIEW_LAT_OPTION, '' ); $lon_raw = get_option( self::PREVIEW_LON_OPTION, '' ); $lat = is_numeric( $lat_raw ) ? (float) $lat_raw : null; $lon = is_numeric( $lon_raw ) ? (float) $lon_raw : null; if ( null !== $lat && null !== $lon ) { return array( 'lat' => $lat, 'lon' => $lon, ); } /** * Filter default map coordinates when no preview lat/lon are saved. * * @param array{lat: float, lon: float} $coords Default coordinates (decimal degrees). */ $default = apply_filters( 'forwp_weather_default_preview_coordinates', array( 'lat' => 51.5074, 'lon' => -0.1278, ) ); if ( ! is_array( $default ) ) { return array( 'lat' => 51.5074, 'lon' => -0.1278, ); } $fallback_lat = isset( $default['lat'] ) && is_numeric( $default['lat'] ) ? (float) $default['lat'] : 51.5074; $fallback_lon = isset( $default['lon'] ) && is_numeric( $default['lon'] ) ? (float) $default['lon'] : -0.1278; return array( 'lat' => $fallback_lat, 'lon' => $fallback_lon, ); } /** * Cooldown seconds for visitor location changes (front end). Clamped 0 … DAY_IN_SECONDS. */ public function get_location_change_cooldown_seconds(): int { $raw = get_option( self::LOCATION_CHANGE_COOLDOWN_OPTION, 60 ); $n = is_numeric( $raw ) ? (int) $raw : 60; if ( $n < 0 ) { return 0; } if ( $n > (int) DAY_IN_SECONDS ) { return (int) DAY_IN_SECONDS; } return $n; } /** * Whether to show a weather summary in the admin bar for administrators. */ public function get_show_admin_bar_weather(): bool { return (bool) get_option( self::SHOW_ADMIN_BAR_WEATHER_OPTION, false ); } /** * Whether to output JSON-LD on the public site (per successful block fetch), not in wp-admin. */ public function get_output_json_ld(): bool { return (bool) get_option( self::OUTPUT_JSON_LD_OPTION, false ); } }