Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Warning display normalizer implementation. #14

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
22 changes: 21 additions & 1 deletion src/Forecast/ForecastPeriod.php
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,11 @@ final class ForecastPeriod {
*/
protected ?string $winds = NULL;

/**
* The fire danger value.
*/
protected ?string $fireDanger = NULL;

/**
* Gets the start time.
*/
Expand Down Expand Up @@ -216,7 +221,7 @@ public function getForecast(): ?string {
/**
* Sets the forecast.
*/
public function setForecast(string $forecast): ForecastPeriod {
public function setForecast(?string $forecast): ForecastPeriod {
$this->forecast = $forecast;
return $this;
}
Expand Down Expand Up @@ -311,4 +316,19 @@ public function setWinds(string $winds): ForecastPeriod {
return $this;
}

/**
* Gets the fire danger value.
*/
public function getFireDanger(): ?string {
return $this->fireDanger;
}

/**
* Sets the fire danger value.
*/
public function setFireDanger(?string $fireDanger): ForecastPeriod {
$this->fireDanger = $fireDanger;
return $this;
}

}
76 changes: 24 additions & 52 deletions src/Forecast/Serializer/ForecastPeriodNormalizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@
namespace BomWeather\Forecast\Serializer;

use BomWeather\Forecast\ForecastPeriod;
use BomWeather\Trait\WeatherDataAccessorTrait;
use BomWeather\Util\BaseNormalizer;

/**
* Location period normalizer.
*/
class ForecastPeriodNormalizer extends BaseNormalizer {

use WeatherDataAccessorTrait;

protected string|array $supportedInterfaceOrClass = ForecastPeriod::class;

/**
Expand Down Expand Up @@ -57,24 +60,14 @@ public function denormalize($data, $type, $format = NULL, array $context = []) {
* The period.
*/
protected function setElementValue(array $element, ForecastPeriod $period): void {
switch ($element['@type']) {
case 'forecast_icon_code':
$period->setIconCode($element['#']);
break;

case 'air_temperature_minimum':
$period->setAirTempMinimum((int) $element['#']);
break;

case 'air_temperature_maximum':
$period->setAirTempMaximum((int) $element['#']);
break;

case 'precipitation_range':
$period->setPrecipitationRange($element['#']);
break;

}
$value = $this->accessWeatherData($element, '#');
match ($element['@type']) {
'forecast_icon_code' => $period->setIconCode($value),
'air_temperature_minimum' => $period->setAirTempMinimum((int) $value),
'air_temperature_maximum' => $period->setAirTempMaximum((int) $value),
'precipitation_range' => $period->setPrecipitationRange($value),
default => '',
};
}

/**
Expand All @@ -86,40 +79,19 @@ protected function setElementValue(array $element, ForecastPeriod $period): void
* The period.
*/
public function setTextValue(array $text, ForecastPeriod $period): void {
switch ($text['@type']) {
case 'precis':
$period->setPrecis($text['#']);
break;

case 'probability_of_precipitation':
$period->setProbabilityOfPrecipitation($text['#']);
break;

case 'forecast':
$period->setForecast($text['#']);
break;

case 'uv_alert':
$period->setUvAlert($text['#']);
break;

case 'forecast_seas':
$period->setSeas($text['#']);
break;

case 'forecast_swell1':
$period->setSwell($text['#']);
break;

case 'forecast_weather':
$period->setWeather($text['#']);
break;

case 'forecast_winds':
$period->setWinds($text['#']);
break;

}
$value = $this->accessWeatherData($text, '#');
match ($text['@type']) {
'precis' => $period->setPrecis($value),
'probability_of_precipitation' => $period->setProbabilityOfPrecipitation($value),
'forecast' => $period->setForecast($value),
'uv_alert' => $period->setUvAlert($value),
'forecast_seas' => $period->setSeas($value),
'forecast_swell1' => $period->setSwell($value),
'forecast_weather' => $period->setWeather($value),
'forecast_winds' => $period->setWinds($value),
'fire_danger' => $period->setFireDanger($value),
default => '',
};
}

}
30 changes: 30 additions & 0 deletions src/Trait/WeatherDataAccessorTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

declare(strict_types=1);

namespace BomWeather\Trait;

/**
* Trait to provide general data validation and access methods.
*/
trait WeatherDataAccessorTrait {

/**
* Access the weather data attribute from weather data array.
*
* @param array|null $weatherData
* Array of weather data.
* @param string $key
* Array key to fetch the data.
*/
public function accessWeatherData(?array $weatherData, string $key): mixed {
if (!$weatherData) {
return NULL;
}
if (!\array_key_exists($key, $weatherData)) {
return '';
}
return $weatherData[$key] ?? '';
}

}
70 changes: 70 additions & 0 deletions src/Warning/Serializer/WarningInfoNormalizer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?php

declare(strict_types=1);

namespace BomWeather\Warning\Serializer;

use BomWeather\Trait\WeatherDataAccessorTrait;
use BomWeather\Util\BaseNormalizer;
use BomWeather\Warning\WarningInfo;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;

/**
* Forecast normalizer.
*/
class WarningInfoNormalizer extends BaseNormalizer {

use WeatherDataAccessorTrait;

/**
* {@inheritdoc}
*/
protected string|array $supportedInterfaceOrClass = WarningInfo::class;

/**
* {@inheritdoc}
*/
public function denormalize($data, $type, $format = NULL, array $context = []) {
if (!$this->serializer instanceof DenormalizerInterface) {
throw new \RuntimeException('The serializer must implement the DenormalizerInterface.');
}

$warningInfo = (new WarningInfo());

if (isset($data['text'])) {
if ($this->isAssoc($data['text'])) {
$text = $data['text'];
$this->setTextValue($text, $warningInfo);
}
else {
\array_map(function ($text) use ($warningInfo): void {
$this->setTextValue($text, $warningInfo);
}, $data['text'], [$warningInfo]);
}
}

return $warningInfo;
}

/**
* Sets a text value.
*
* @param array $text
* The text array.
* @param \BomWeather\Warning\WarningInfo $warningInfo
* The warning info.
*/
public function setTextValue(array $text, WarningInfo $warningInfo): void {
$value = \array_key_exists('#', $text) ? $this->accessWeatherData($text, '#') : $this->accessWeatherData($text, 'p');
match ($text['@type']) {
'warning_title' => $warningInfo->setWarningTitle($value),
'preamble' => $warningInfo->setPreamble($value),
'warning_advice' => \is_array($value) ? \array_map(function ($advice) use ($warningInfo): void {
$warningInfo->setWarningAdvice($advice);
}, $value) : $warningInfo->setWarningAdvice($value),
'warning_next_issue' => $warningInfo->setWarningNextIssue($value),
default => '',
};
}

}
83 changes: 83 additions & 0 deletions src/Warning/Serializer/WarningNormalizer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<?php

declare(strict_types=1);

namespace BomWeather\Warning\Serializer;

use BomWeather\Forecast\Area;
use BomWeather\Util\BaseNormalizer;
use BomWeather\Warning\Warning;
use BomWeather\Warning\WarningInfo;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;

/**
* Forecast normalizer.
*/
class WarningNormalizer extends BaseNormalizer {

/**
* {@inheritdoc}
*/
protected string|array $supportedInterfaceOrClass = Warning::class;

/**
* {@inheritdoc}
*/
public function denormalize($data, $type, $format = NULL, array $context = []) {
if (!$this->serializer instanceof DenormalizerInterface) {
throw new \RuntimeException('The serializer must implement the DenormalizerInterface.');
}

$warning = (new Warning())
->setIssueTime($this->serializer->denormalize($data['amoc']['issue-time-utc'], \DateTimeImmutable::class));

if (\array_key_exists('warning', $data)) {
if ($this->isAssoc($data['warning']['area'])) {
$area = $data['warning']['area'];
$this->setValue($area, $warning);
}
else {
\array_map(function ($area) use ($warning): void {
$this->setValue($area, $warning);
}, $data['warning']['area'], [$warning]);
}
$warningInfo = $this->serializer->denormalize($data['warning']['warning-info'], WarningInfo::class);
$warning->setWarningInfo($warningInfo);
}

return $warning;
}

/**
* Sets the area value.
*
* @param array $area
* The area data.
* @param \BomWeather\Warning\Warning $warning
* The warning.
*/
public function setValue(array $area, Warning $warning): void {
switch ($area['@type']) {
case Area::TYPE_REGION:
$warning->addRegion($this->serializer->denormalize($area, Area::class));
break;

case Area::TYPE_DISTRICT:
$warning->addDistrict($this->serializer->denormalize($area, Area::class));
break;

case Area::TYPE_METROPOLITAN:
$warning->addMetropolitanArea($this->serializer->denormalize($area, Area::class));
break;

case Area::TYPE_LOCATION:
$warning->addLocation($this->serializer->denormalize($area, Area::class));
break;

case Area::TYPE_COAST:
$warning->addCoast($this->serializer->denormalize($area, Area::class));
break;
}
}

}
39 changes: 39 additions & 0 deletions src/Warning/Serializer/WarningSerializerFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

declare(strict_types=1);

namespace BomWeather\Warning\Serializer;

use BomWeather\Forecast\Serializer\AreaNormalizer;
use BomWeather\Forecast\Serializer\ForecastPeriodNormalizer;
use Symfony\Component\Serializer\Encoder\XmlEncoder;
use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
use Symfony\Component\Serializer\Serializer;

/**
* Factory for creating a weather warning data.
*/
class WarningSerializerFactory {

/**
* Creates a new forecast serializer.
*
* @param string $rootNode
* (optional) The root node of the XML.
*
* @return \Symfony\Component\Serializer\Serializer
* The serializer.
*/
public static function create(string $rootNode = 'product'): Serializer {
$encoders = [new XmlEncoder([XmlEncoder::ROOT_NODE_NAME => $rootNode])];
$normalizers = [
new DateTimeNormalizer([DateTimeNormalizer::TIMEZONE_KEY => 'UTC']),
new WarningNormalizer(),
new WarningInfoNormalizer(),
new AreaNormalizer(),
new ForecastPeriodNormalizer(),
];
return new Serializer($normalizers, $encoders);
}

}
Loading