|
19 | 19 |
|
20 | 20 | use Cmfcmf\OpenWeatherMap\AbstractCache;
|
21 | 21 | use Cmfcmf\OpenWeatherMap\CurrentWeather;
|
| 22 | +use Cmfcmf\OpenWeatherMap\UVIndex; |
22 | 23 | use Cmfcmf\OpenWeatherMap\CurrentWeatherGroup;
|
23 | 24 | use Cmfcmf\OpenWeatherMap\Exception as OWMException;
|
24 | 25 | use Cmfcmf\OpenWeatherMap\Fetcher\CurlFetcher;
|
@@ -67,6 +68,11 @@ class OpenWeatherMap
|
67 | 68 | */
|
68 | 69 | private $weatherHistoryUrl = 'http://history.openweathermap.org/data/2.5/history/city?';
|
69 | 70 |
|
| 71 | + /** |
| 72 | + * @var string The basic api url to fetch uv index data from. |
| 73 | + */ |
| 74 | + private $uvIndexUrl = 'http://api.openweathermap.org/v3/uvi'; |
| 75 | + |
70 | 76 | /**
|
71 | 77 | * @var AbstractCache|bool $cache The cache to use.
|
72 | 78 | */
|
@@ -303,6 +309,52 @@ public function getWeatherHistory($query, \DateTime $start, $endOrCount = 1, $ty
|
303 | 309 | return new WeatherHistory($xml, $query);
|
304 | 310 | }
|
305 | 311 |
|
| 312 | + /** |
| 313 | + * Returns the current uv index at the location you specified. |
| 314 | + * |
| 315 | + * @param float $lat The location's latitude. |
| 316 | + * @param float $lon The location's longitude. |
| 317 | + * |
| 318 | + * @throws OpenWeatherMap\Exception If OpenWeatherMap returns an error. |
| 319 | + * @throws \InvalidArgumentException If an argument error occurs. |
| 320 | + * |
| 321 | + * @return UVIndex The uvi object. |
| 322 | + * |
| 323 | + * @api |
| 324 | + */ |
| 325 | + public function getCurrentUVIndex($lat, $lon) |
| 326 | + { |
| 327 | + $answer = $this->getRawCurrentUVIndexData($lat, $lon); |
| 328 | + $json = $this->parseJson($answer); |
| 329 | + |
| 330 | + return new UVIndex($json); |
| 331 | + } |
| 332 | + |
| 333 | + /** |
| 334 | + * Returns the uv index at date, time and location you specified. |
| 335 | + * |
| 336 | + * @param float $lat The location's latitude. |
| 337 | + * @param float $lon The location's longitude. |
| 338 | + * @param \DateTimeInterface $dateTime The date and time to request data for. |
| 339 | + * @param string $timePrecision This decides about the timespan OWM will look for the uv index. The tighter |
| 340 | + * the timespan, the less likely it is to get a result. Can be 'year', 'month', |
| 341 | + * 'day', 'hour', 'minute' or 'second', defaults to 'day'. |
| 342 | + * |
| 343 | + * @throws OpenWeatherMap\Exception If OpenWeatherMap returns an error. |
| 344 | + * @throws \InvalidArgumentException If an argument error occurs. |
| 345 | + * |
| 346 | + * @return UVIndex The uvi object. |
| 347 | + * |
| 348 | + * @api |
| 349 | + */ |
| 350 | + public function getUVIndex($lat, $lon, $dateTime, $timePrecision = 'day') |
| 351 | + { |
| 352 | + $answer = $this->getRawUVIndexData($lat, $lon, $dateTime, $timePrecision); |
| 353 | + $json = $this->parseJson($answer); |
| 354 | + |
| 355 | + return new UVIndex($json); |
| 356 | + } |
| 357 | + |
306 | 358 | /**
|
307 | 359 | * Directly returns the xml/json/html string returned by OpenWeatherMap for the current weather.
|
308 | 360 | *
|
@@ -396,7 +448,7 @@ public function getRawDailyForecastData($query, $units = 'imperial', $lang = 'en
|
396 | 448 | }
|
397 | 449 |
|
398 | 450 | /**
|
399 |
| - * Directly returns the xml/json/html string returned by OpenWeatherMap for the weather history. |
| 451 | + * Directly returns the json string returned by OpenWeatherMap for the weather history. |
400 | 452 | *
|
401 | 453 | * @param array|int|string $query The place to get weather information for. For possible values see ::getWeather.
|
402 | 454 | * @param \DateTime $start The \DateTime object of the date to get the first weather information from.
|
@@ -436,6 +488,59 @@ public function getRawWeatherHistory($query, \DateTime $start, $endOrCount = 1,
|
436 | 488 | return $this->cacheOrFetchResult($url);
|
437 | 489 | }
|
438 | 490 |
|
| 491 | + /** |
| 492 | + * Directly returns the json string returned by OpenWeatherMap for the current UV index data. |
| 493 | + * |
| 494 | + * @param float $lat The location's latitude. |
| 495 | + * @param float $lon The location's longitude. |
| 496 | + * |
| 497 | + * @return bool|string Returns the fetched data. |
| 498 | + * |
| 499 | + * @api |
| 500 | + */ |
| 501 | + public function getRawCurrentUVIndexData($lat, $lon) |
| 502 | + { |
| 503 | + if (!$this->apiKey) { |
| 504 | + throw new \RuntimeException('Before using this method, you must set the api key using ->setApiKey()'); |
| 505 | + } |
| 506 | + if (!is_float($lat) || !is_float($lon)) { |
| 507 | + throw new \InvalidArgumentException('$lat and $lon must be floating point numbers'); |
| 508 | + } |
| 509 | + $url = $this->buildUVIndexUrl($lat, $lon); |
| 510 | + |
| 511 | + return $this->cacheOrFetchResult($url); |
| 512 | + } |
| 513 | + |
| 514 | + /** |
| 515 | + * Directly returns the json string returned by OpenWeatherMap for the UV index data. |
| 516 | + * |
| 517 | + * @param float $lat The location's latitude. |
| 518 | + * @param float $lon The location's longitude. |
| 519 | + * @param \DateTimeInterface $dateTime The date and time to request data for. |
| 520 | + * @param string $timePrecision This decides about the timespan OWM will look for the uv index. The tighter |
| 521 | + * the timespan, the less likely it is to get a result. Can be 'year', 'month', |
| 522 | + * 'day', 'hour', 'minute' or 'second', defaults to 'day'. |
| 523 | + * |
| 524 | + * @return bool|string Returns the fetched data. |
| 525 | + * |
| 526 | + * @api |
| 527 | + */ |
| 528 | + public function getRawUVIndexData($lat, $lon, $dateTime, $timePrecision = 'day') |
| 529 | + { |
| 530 | + if (!$this->apiKey) { |
| 531 | + throw new \RuntimeException('Before using this method, you must set the api key using ->setApiKey()'); |
| 532 | + } |
| 533 | + if (!is_float($lat) || !is_float($lon)) { |
| 534 | + throw new \InvalidArgumentException('$lat and $lon must be floating point numbers'); |
| 535 | + } |
| 536 | + if (interface_exists('DateTimeInterface') && !$dateTime instanceof \DateTimeInterface || !$dateTime instanceof \DateTime) { |
| 537 | + throw new \InvalidArgumentException('$dateTime must be an instance of \DateTime or \DateTimeInterface'); |
| 538 | + } |
| 539 | + $url = $this->buildUVIndexUrl($lat, $lon, $dateTime, $timePrecision); |
| 540 | + |
| 541 | + return $this->cacheOrFetchResult($url); |
| 542 | + } |
| 543 | + |
439 | 544 | /**
|
440 | 545 | * Returns whether or not the last result was fetched from the cache.
|
441 | 546 | *
|
@@ -503,6 +608,50 @@ private function buildUrl($query, $units, $lang, $appid, $mode, $url)
|
503 | 608 | return $url;
|
504 | 609 | }
|
505 | 610 |
|
| 611 | + /** |
| 612 | + * @param float $lat |
| 613 | + * @param float $lon |
| 614 | + * @param \DateTime|\DateTimeImmutable $dateTime |
| 615 | + * @param string $timePrecision |
| 616 | + * |
| 617 | + * @return string |
| 618 | + */ |
| 619 | + private function buildUVIndexUrl($lat, $lon, $dateTime = null, $timePrecision = null) |
| 620 | + { |
| 621 | + if ($dateTime !== null) { |
| 622 | + $format = '\Z'; |
| 623 | + switch ($timePrecision) { |
| 624 | + /** @noinspection PhpMissingBreakStatementInspection */ |
| 625 | + case 'second': |
| 626 | + $format = ':s' . $format; |
| 627 | + /** @noinspection PhpMissingBreakStatementInspection */ |
| 628 | + case 'minute': |
| 629 | + $format = ':i' . $format; |
| 630 | + /** @noinspection PhpMissingBreakStatementInspection */ |
| 631 | + case 'hour': |
| 632 | + $format = '\TH' . $format; |
| 633 | + /** @noinspection PhpMissingBreakStatementInspection */ |
| 634 | + case 'day': |
| 635 | + $format = '-d' . $format; |
| 636 | + /** @noinspection PhpMissingBreakStatementInspection */ |
| 637 | + case 'month': |
| 638 | + $format = '-m' . $format; |
| 639 | + case 'year': |
| 640 | + $format = 'Y' . $format; |
| 641 | + break; |
| 642 | + default: |
| 643 | + throw new \InvalidArgumentException('$timePrecision is invalid.'); |
| 644 | + } |
| 645 | + // OWM only accepts UTC timezones. |
| 646 | + $dateTime->setTimezone(new \DateTimeZone('UTC')); |
| 647 | + $dateTime = $dateTime->format($format); |
| 648 | + } else { |
| 649 | + $dateTime = 'current'; |
| 650 | + } |
| 651 | + |
| 652 | + return sprintf($this->uvIndexUrl . '/%s,%s/%s.json?appid=%s', $lat, $lon, $dateTime, $this->apiKey); |
| 653 | + } |
| 654 | + |
506 | 655 | /**
|
507 | 656 | * Builds the query string for the url.
|
508 | 657 | *
|
@@ -565,6 +714,9 @@ private function parseJson($answer)
|
565 | 714 | if (json_last_error() !== JSON_ERROR_NONE) {
|
566 | 715 | throw new OWMException('OpenWeatherMap returned an invalid json object. JSON error was: ' . $this->json_last_error_msg());
|
567 | 716 | }
|
| 717 | + if (isset($json->message)) { |
| 718 | + throw new OWMException('An error occurred: '. $json->message); |
| 719 | + } |
568 | 720 |
|
569 | 721 | return $json;
|
570 | 722 | }
|
|
0 commit comments