View source
<?php
namespace Drupal\weather\Service;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Datetime\DateFormatterInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Link;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\Theme\ThemeManagerInterface;
use Drupal\Core\Url;
use Drupal\weather\Entity\WeatherDisplayPlaceInterface;
class ThemeService {
use StringTranslationTrait;
protected $entityTypeManager;
protected $weatherHelper;
protected $weatherParser;
protected $weatherDataService;
protected $weatherConfig;
protected $themeManager;
protected $dateFormatter;
protected $weatherPlaceStorage;
public function __construct(EntityTypeManagerInterface $entity_type_manager, HelperService $weather_helper, ParserService $parserService, DataService $weather_data_service, ConfigFactoryInterface $configFactory, ThemeManagerInterface $themeManager, DateFormatterInterface $dateFormatter) {
$this->entityTypeManager = $entity_type_manager;
$this->weatherHelper = $weather_helper;
$this->weatherDataService = $weather_data_service;
$this->weatherConfig = $configFactory
->get('weather.settings');
$this->themeManager = $themeManager;
$this->dateFormatter = $dateFormatter;
$this->weatherPlaceStorage = $entity_type_manager
->getStorage('weather_place');
$this->weatherParser = $parserService;
}
public function preprocessWeatherVariables(&$variables, bool $detailed = FALSE) {
$displayPlaces = [];
$forecast_days = $this->weatherConfig
->get('weather_forecast_days');
$display = $this->weatherHelper
->getDisplayConfig($variables['display_type'], $variables['display_number']);
if ($detailed) {
if ($variables['weather_display_place'] instanceof WeatherDisplayPlaceInterface) {
$displayPlaces = [
$variables['weather_display_place'],
];
$forecast_days = 0;
}
}
else {
$displayPlaces = $this->weatherHelper
->getPlacesInUse($variables['display_type'], $variables['display_number']);
}
foreach ($displayPlaces as $idx => $place) {
$weather = $this->weatherParser
->getWeather($place->geoid->target_id, $forecast_days, $detailed);
$this
->setWeatherVariables($variables, $idx, $place, $weather, $detailed);
$this
->setForecastsVariables($variables, $idx, $weather, $display);
}
}
protected function setWeatherVariables(&$variables, $idx, $place, $weather, bool $detailed = FALSE) {
$variables['weather'][$idx]['utc_offset'] = $weather['utc_offset'];
$variables['weather'][$idx]['name'] = $place->displayed_name->value;
$variables['weather'][$idx]['geoid'] = $place->geoid->target_id;
if (!$detailed) {
$link = $this->weatherHelper
->getLinkForGeoid($place->geoid->target_id, $variables['destination'], $variables['display_number']);
$variables['weather'][$idx]['link'] = Link::fromTextAndUrl($place->displayed_name->value, Url::fromUserInput($link));
}
$link = $this->weatherHelper
->getLinkForGeoid($place->geoid->target_id, 'yr.no');
$variables['weather'][$idx]['yr.no'] = $link;
}
protected function setForecastsVariables(&$variables, $idx, $weather, $display) {
$day_counter = 0;
$forecasts = [];
foreach ($weather['forecasts'] as $date => $time_ranges) {
$formatted_date = $this->dateFormatter
->format(strtotime($date), 'weather_short');
if ($day_counter == 0) {
$formatted_date = $this
->t('Today, @date', [
'@date' => $formatted_date,
]);
}
elseif ($day_counter == 1) {
$formatted_date = $this
->t('Tomorrow, @date', [
'@date' => $formatted_date,
]);
}
$forecasts[$date]['formatted_date'] = $formatted_date;
if ($display['show_sunrise_sunset']) {
$forecasts[$date]['sun_info'] = $this
->calculateSunInfo($date, $variables['weather'][$idx]['utc_offset'], $variables['weather'][$idx]['geoid']);
}
foreach ($time_ranges as $time_range => $data) {
$condition = $this
->formatCondition($data['symbol']);
$forecasts[$date]['time_ranges'][$time_range]['condition'] = $condition;
$forecasts[$date]['time_ranges'][$time_range]['symbol'] = $this
->formatImage($data['symbol'], $condition);
$forecasts[$date]['time_ranges'][$time_range]['temperature'] = $this
->formatTemperature($data['temperature'], $display['temperature']);
if ($display['show_windchill_temperature']) {
$forecasts[$date]['time_ranges'][$time_range]['windchill'] = $this
->formatWindchillTemperature($data['temperature'], $data['wind_speed'], $display['temperature']);
}
$forecasts[$date]['time_ranges'][$time_range]['precipitation'] = $this
->t('@precipitation mm', [
'@precipitation' => $data['precipitation'],
]);
$forecasts[$date]['time_ranges'][$time_range]['pressure'] = $this
->formatPressure($data['pressure'], $display['pressure']);
$forecasts[$date]['time_ranges'][$time_range]['wind'] = $this
->formatWind($data['wind_direction'], $data['wind_speed'], $display['windspeed'], $display['show_abbreviated_directions'], $display['show_directions_degree']);
}
$day_counter++;
}
$variables['weather'][$idx]['forecasts'] = $forecasts;
}
protected function calculateSunInfo($date, $utc_offset, $geoid) {
$weatherPlace = $this->weatherPlaceStorage
->load($geoid);
$time = strtotime($date . ' 12:00:00 UTC') - 60 * $utc_offset;
$sun_info = date_sun_info($time, $weatherPlace->latitude->value, $weatherPlace->longitude->value);
if ($sun_info['sunrise'] == 0 and $sun_info['sunset'] == 0) {
$result = $this
->t('No sunrise, polar night');
}
elseif ($sun_info['sunrise'] == 1 and $sun_info['sunset'] == 1) {
$result = $this
->t('No sunset, polar day');
}
else {
$time = round($sun_info['sunrise'] / 60) * 60;
$time = gmdate('H:i', $time + 60 * $utc_offset);
$result['sunrise'] = $time;
$time = round($sun_info['sunset'] / 60) * 60;
$time = gmdate('H:i', $time + 60 * $utc_offset);
$result['sunset'] = $time;
}
return $result;
}
protected function formatImage($symbol, $condition) {
$theme_path = $this->themeManager
->getActiveTheme()
->getPath();
$custom_path = $theme_path . '/' . $this->weatherConfig
->get('weather_image_directory') . '/';
$image = $custom_path . $symbol . '.png';
if (!is_readable($image)) {
$default_path = drupal_get_path('module', 'weather') . '/images/';
$image = $default_path . $symbol . '.png';
}
$size = getimagesize($image);
return [
'#theme' => 'image',
'#uri' => $image,
'#width' => $size[0],
'#height' => $size[1],
'#alt' => $condition,
'#title' => $condition,
'#attributes' => [
'class' => 'weather-image',
],
];
}
protected function formatTemperature($temperature, $unit) {
$fahrenheit = (int) ($temperature * 9 / 5) + 32;
if ($unit == 'fahrenheit') {
$result = $this
->t('@temperature °F', [
'@temperature' => $fahrenheit,
]);
}
elseif ($unit == 'celsiusfahrenheit') {
$result = $this
->t('@temperature_c °C / @temperature_f °F', [
'@temperature_c' => $temperature,
'@temperature_f' => $fahrenheit,
]);
}
elseif ($unit == 'fahrenheitcelsius') {
$result = $this
->t('@temperature_f °F / @temperature_c °C', [
'@temperature_f' => $fahrenheit,
'@temperature_c' => $temperature,
]);
}
elseif ($unit == 'celsius_value') {
$result = $temperature;
}
elseif ($unit == 'fahrenheit_value') {
$result = $fahrenheit;
}
else {
$result = $this
->t('@temperature °C', [
'@temperature' => $temperature,
]);
}
return [
'#markup' => preg_replace("/([^ ]*) ([^ ]*)/", '<span style="white-space:nowrap;">\\1 \\2</span>', $result),
];
}
protected function formatWindchillTemperature($temperature, $wind_speed, $unit) {
$result = NULL;
if ($temperature <= 10 and $wind_speed >= 1.34) {
$wind_speed = $wind_speed * 3.6;
$windchill = (int) round(13.12 + 0.6215000000000001 * $temperature - 11.37 * pow($wind_speed, 0.16) + 0.3965 * $temperature * pow($wind_speed, 0.16));
$result = $this
->formatTemperature($windchill, $unit);
}
return $result;
}
protected function formatCondition($condition_no) {
$condition_no = substr($condition_no, 0, 2);
switch ($condition_no) {
case 1:
$txt = $this
->t('Clear sky');
break;
case 2:
$txt = $this
->t('Fair');
break;
case 3:
$txt = $this
->t('Partly cloudy');
break;
case 4:
$txt = $this
->t('Cloudy');
break;
case 5:
$txt = $this
->t('Rain showers');
break;
case 6:
$txt = $this
->t('Rain showers and thunder');
break;
case 7:
$txt = $this
->t('Sleet showers');
break;
case 8:
$txt = $this
->t('Snow showers');
break;
case 9:
$txt = $this
->t('Rain');
break;
case 10:
$txt = $this
->t('Heavy rain');
break;
case 11:
$txt = $this
->t('Heavy rain and thunder');
break;
case 12:
$txt = $this
->t('Sleet');
break;
case 13:
$txt = $this
->t('Snow');
break;
case 14:
$txt = $this
->t('Snow and thunder');
break;
case 15:
$txt = $this
->t('Fog');
break;
case 20:
$txt = $this
->t('Sleet showers and thunder');
break;
case 21:
$txt = $this
->t('Snow showers and thunder');
break;
case 22:
$txt = $this
->t('Rain and thunder');
break;
case 23:
$txt = $this
->t('Sleet and thunder');
break;
case 24:
$txt = $this
->t('Light rain showers and thunder');
break;
case 25:
$txt = $this
->t('Heavy rain showers and thunder');
break;
case 26:
$txt = $this
->t('Light sleet showers and thunder');
break;
case 27:
$txt = $this
->t('Heavy sleet showers and thunder');
break;
case 28:
$txt = $this
->t('Light snow showers and thunder');
break;
case 29:
$txt = $this
->t('Heavy snow showers and thunder');
break;
case 30:
$txt = $this
->t('Light rain and thunder');
break;
case 31:
$txt = $this
->t('Light sleet and thunder');
break;
case 32:
$txt = $this
->t('Heavy sleet and thunder');
break;
case 33:
$txt = $this
->t('Light snow and thunder');
break;
case 34:
$txt = $this
->t('Heavy snow and thunder');
break;
case 40:
$txt = $this
->t('Light rain showers');
break;
case 41:
$txt = $this
->t('Heavy rain showers');
break;
case 42:
$txt = $this
->t('Light sleet showers');
break;
case 43:
$txt = $this
->t('Heavy sleet showers');
break;
case 44:
$txt = $this
->t('Light snow showers');
break;
case 45:
$txt = $this
->t('Heavy snow showers');
break;
case 46:
$txt = $this
->t('Light rain');
break;
case 47:
$txt = $this
->t('Light sleet');
break;
case 48:
$txt = $this
->t('Heavy sleet');
break;
case 49:
$txt = $this
->t('Light snow');
break;
case 50:
$txt = $this
->t('Heavy snow');
break;
default:
$txt = $this
->t('No data');
}
return $txt;
}
protected function formatPressure($pressure, $unit) {
if ($unit == 'inhg') {
$result = $this
->t('@pressure inHg', [
'@pressure' => round($pressure * 0.02953, 2),
]);
}
elseif ($unit == 'inhg_value') {
$result = round($pressure * 0.02953, 2);
}
elseif ($unit == 'mmhg') {
$result = $this
->t('@pressure mmHg', [
'@pressure' => round($pressure * 0.7500599999999999, 0),
]);
}
elseif ($unit == 'mmhg_value') {
$result = round($pressure * 0.7500599999999999, 0);
}
elseif ($unit == 'kpa') {
$result = $this
->t('@pressure kPa', [
'@pressure' => round($pressure / 10, 1),
]);
}
elseif ($unit == 'kpa_value') {
$result = round($pressure / 10, 1);
}
elseif ($unit == 'hpa_value') {
$result = $pressure;
}
else {
$result = $this
->t('@pressure hPa', [
'@pressure' => $pressure,
]);
}
return [
'#markup' => preg_replace("/([^ ]*) ([^ ]*)/", '<span style="white-space:nowrap;">\\1 \\2</span>', $result),
];
}
protected function formatWind($wind_direction, $wind_speed, $unit, $abbreviated, $exact_degree) {
$direction = $this
->bearingToText($wind_direction, $abbreviated);
$beaufort = $this
->calculateBeaufort($wind_speed);
$speed = $this
->formatWindSpeed($wind_speed, $unit);
if ($exact_degree) {
$result = $this
->t('@description, <span style="white-space:nowrap;">@speed</span> from @direction (@degree°)', [
'@description' => $beaufort['description'],
'@speed' => $speed,
'@direction' => $direction,
'@degree' => $wind_direction,
]);
}
else {
$result = $this
->t('@description, @speed from @direction', [
'@description' => $beaufort['description'],
'@speed' => $speed,
'@direction' => $direction,
]);
}
return $result;
}
protected function bearingToText($bearing, $abbreviated = FALSE) {
$sector = floor(($bearing + 11.25) / 22.5) % 16;
if (!$abbreviated) {
$direction = [
$this
->t('North'),
$this
->t('North-Northeast'),
$this
->t('Northeast'),
$this
->t('East-Northeast'),
$this
->t('East'),
$this
->t('East-Southeast'),
$this
->t('Southeast'),
$this
->t('South-Southeast'),
$this
->t('South'),
$this
->t('South-Southwest'),
$this
->t('Southwest'),
$this
->t('West-Southwest'),
$this
->t('West'),
$this
->t('West-Northwest'),
$this
->t('Northwest'),
$this
->t('North-Northwest'),
];
}
else {
$direction = [
$this
->t('N'),
$this
->t('NNE'),
$this
->t('NE'),
$this
->t('ENE'),
$this
->t('E'),
$this
->t('ESE'),
$this
->t('SE'),
$this
->t('SSE'),
$this
->t('S'),
$this
->t('SSW'),
$this
->t('SW'),
$this
->t('WSW'),
$this
->t('W'),
$this
->t('WNW'),
$this
->t('NW'),
$this
->t('NNW'),
];
}
return $direction[$sector];
}
protected function calculateBeaufort($wind_speed) {
$description = [
$this
->t('Calm'),
$this
->t('Light air'),
$this
->t('Light breeze'),
$this
->t('Gentle breeze'),
$this
->t('Moderate breeze'),
$this
->t('Fresh breeze'),
$this
->t('Strong breeze'),
$this
->t('Near gale'),
$this
->t('Gale'),
$this
->t('Strong gale'),
$this
->t('Storm'),
$this
->t('Violent storm'),
$this
->t('Hurricane'),
];
$number = 0;
if ($wind_speed >= 0.3) {
$number = 1;
}
if ($wind_speed >= 1.6) {
$number = 2;
}
if ($wind_speed >= 3.5) {
$number = 3;
}
if ($wind_speed >= 5.5) {
$number = 4;
}
if ($wind_speed >= 8.0) {
$number = 5;
}
if ($wind_speed >= 10.8) {
$number = 6;
}
if ($wind_speed >= 13.9) {
$number = 7;
}
if ($wind_speed >= 17.2) {
$number = 8;
}
if ($wind_speed >= 20.8) {
$number = 9;
}
if ($wind_speed >= 24.5) {
$number = 10;
}
if ($wind_speed >= 28.5) {
$number = 11;
}
if ($wind_speed >= 32.7) {
$number = 12;
}
return [
'number' => $number,
'description' => $description[$number],
];
}
protected function formatWindSpeed($wind_speed, $unit) {
if ($unit == 'mph') {
$result = $this
->t('@speed mph', [
'@speed' => round($wind_speed * 2.23694, 1),
]);
}
elseif ($unit == 'mph_value') {
$result = round($wind_speed * 2.23694, 1);
}
elseif ($unit == 'knots') {
$result = $this
->t('@speed knots', [
'@speed' => round($wind_speed * 1.94384, 1),
]);
}
elseif ($unit == 'knots_value') {
$result = round($wind_speed * 1.94384, 1);
}
elseif ($unit == 'kmh') {
$result = $this
->t('@speed km/h', [
'@speed' => round($wind_speed * 3.6, 1),
]);
}
elseif ($unit == 'kmh_value') {
$result = round($wind_speed * 3.6, 1);
}
elseif ($unit == 'beaufort') {
$beaufort = $this
->calculateBeaufort($wind_speed);
$result = $this
->t('Beaufort @number', [
'@number' => $beaufort['number'],
]);
}
elseif ($unit == 'beaufort_value') {
$beaufort = $this
->calculateBeaufort($wind_speed);
$result = $beaufort['number'];
}
elseif ($unit == 'mps_value') {
$result = $wind_speed;
}
else {
$result = $this
->t('@speed meter/s', [
'@speed' => $wind_speed,
]);
}
return $result;
}
}