@@ -71,7 +71,7 @@ class OpenWeatherMap
71
71
/**
72
72
* @var string The basic api url to fetch uv index data from.
73
73
*/
74
- private $ uvIndexUrl = 'https://api.openweathermap.org/v3 /uvi ' ;
74
+ private $ uvIndexUrl = 'https://api.openweathermap.org/data/2.5 /uvi ' ;
75
75
76
76
/**
77
77
* @var AbstractCache|bool $cache The cache to use.
@@ -315,47 +315,73 @@ public function getWeatherHistory($query, \DateTime $start, $endOrCount = 1, $ty
315
315
/**
316
316
* Returns the current uv index at the location you specified.
317
317
*
318
- * @param float $lat The location's latitude.
319
- * @param float $lon The location's longitude.
318
+ * @param float $lat The location's latitude.
319
+ * @param float $lon The location's longitude.
320
320
*
321
321
* @throws OpenWeatherMap\Exception If OpenWeatherMap returns an error.
322
322
* @throws \InvalidArgumentException If an argument error occurs.
323
323
*
324
- * @return UVIndex The uvi object.
324
+ * @return UVIndex
325
325
*
326
326
* @api
327
327
*/
328
328
public function getCurrentUVIndex ($ lat , $ lon )
329
329
{
330
- $ answer = $ this ->getRawCurrentUVIndexData ( $ lat , $ lon );
330
+ $ answer = $ this ->getRawUVIndexData ( ' current ' , $ lat , $ lon );
331
331
$ json = $ this ->parseJson ($ answer );
332
332
333
333
return new UVIndex ($ json );
334
334
}
335
335
336
336
/**
337
- * Returns the uv index at date, time and location you specified.
337
+ * Returns a forecast of the uv index at the specified location.
338
+ * The optional $cnt parameter determines the number of days to forecase.
339
+ * The maximum supported number of days is 8.
338
340
*
339
- * @param float $lat The location's latitude.
340
- * @param float $lon The location's longitude.
341
- * @param \DateTimeInterface $dateTime The date and time to request data for.
342
- * @param string $timePrecision This decides about the timespan OWM will look for the uv index. The tighter
343
- * the timespan, the less likely it is to get a result. Can be 'year', 'month',
344
- * 'day', 'hour', 'minute' or 'second', defaults to 'day'.
341
+ * @param float $lat The location's latitude.
342
+ * @param float $lon The location's longitude.
343
+ * @param int $cnt Number of returned days (default to 8).
345
344
*
346
345
* @throws OpenWeatherMap\Exception If OpenWeatherMap returns an error.
347
346
* @throws \InvalidArgumentException If an argument error occurs.
348
347
*
349
- * @return UVIndex The uvi object.
348
+ * @return UVIndex[]
350
349
*
351
350
* @api
352
351
*/
353
- public function getUVIndex ($ lat , $ lon , $ dateTime , $ timePrecision = ' day ' )
352
+ public function getForecastUVIndex ($ lat , $ lon , $ cnt = 8 )
354
353
{
355
- $ answer = $ this ->getRawUVIndexData ($ lat , $ lon , $ dateTime , $ timePrecision );
356
- $ json = $ this ->parseJson ($ answer );
354
+ $ answer = $ this ->getRawUVIndexData (' forecast ' , $ lat , $ lon , $ cnt );
355
+ $ data = $ this ->parseJson ($ answer );
357
356
358
- return new UVIndex ($ json );
357
+ return array_map (function ($ entry ) {
358
+ return new UVIndex ($ entry );
359
+ }, $ data );
360
+ }
361
+
362
+ /**
363
+ * Returns the historic uv index at the specified location.
364
+ *
365
+ * @param float $lat The location's latitude.
366
+ * @param float $lon The location's longitude.
367
+ * @param \DateTime $start Starting point of time period.
368
+ * @param \DateTime $end Final point of time period.
369
+ *
370
+ * @throws OpenWeatherMap\Exception If OpenWeatherMap returns an error.
371
+ * @throws \InvalidArgumentException If an argument error occurs.
372
+ *
373
+ * @return UVIndex[]
374
+ *
375
+ * @api
376
+ */
377
+ public function getHistoricUVIndex ($ lat , $ lon , $ start , $ end )
378
+ {
379
+ $ answer = $ this ->getRawUVIndexData ('historic ' , $ lat , $ lon , null , $ start , $ end );
380
+ $ data = $ this ->parseJson ($ answer );
381
+
382
+ return array_map (function ($ entry ) {
383
+ return new UVIndex ($ entry );
384
+ }, $ data );
359
385
}
360
386
361
387
/**
@@ -492,55 +518,45 @@ public function getRawWeatherHistory($query, \DateTime $start, $endOrCount = 1,
492
518
}
493
519
494
520
/**
495
- * Directly returns the json string returned by OpenWeatherMap for the current UV index data.
521
+ * Directly returns the json string returned by OpenWeatherMap for the UV index data.
496
522
*
497
- * @param float $lat The location's latitude.
498
- * @param float $lon The location's longitude.
523
+ * @param string $mode The type of requested data (['historic', 'forecast', 'current']).
524
+ * @param float $lat The location's latitude.
525
+ * @param float $lon The location's longitude.
526
+ * @param int $cnt Number of returned days (only allowed for 'forecast' data).
527
+ * @param \DateTime $start Starting point of time period (only allowed and required for 'historic' data).
528
+ * @param \DateTime $end Final point of time period (only allowed and required for 'historic' data).
499
529
*
500
530
* @return bool|string Returns the fetched data.
501
531
*
502
532
* @api
503
533
*/
504
- public function getRawCurrentUVIndexData ( $ lat , $ lon )
534
+ public function getRawUVIndexData ( $ mode , $ lat , $ lon, $ cnt = null , $ start = null , $ end = null )
505
535
{
506
- if (!$ this -> apiKey ) {
507
- throw new \RuntimeException ( ' Before using this method, you must set the api key using ->setApiKey() ' );
536
+ if (!in_array ( $ mode , array ( ' current ' , ' forecast ' , ' historic ' ), true ) ) {
537
+ throw new \InvalidArgumentException ( " $ mode must be one of 'historic', 'forecast', 'current'. " );
508
538
}
509
539
if (!is_float ($ lat ) || !is_float ($ lon )) {
510
540
throw new \InvalidArgumentException ('$lat and $lon must be floating point numbers ' );
511
541
}
512
- $ url = $ this ->buildUVIndexUrl ($ lat , $ lon );
513
-
514
- return $ this ->cacheOrFetchResult ($ url );
515
- }
516
-
517
- /**
518
- * Directly returns the json string returned by OpenWeatherMap for the UV index data.
519
- *
520
- * @param float $lat The location's latitude.
521
- * @param float $lon The location's longitude.
522
- * @param \DateTimeInterface $dateTime The date and time to request data for.
523
- * @param string $timePrecision This decides about the timespan OWM will look for the uv index. The tighter
524
- * the timespan, the less likely it is to get a result. Can be 'year', 'month',
525
- * 'day', 'hour', 'minute' or 'second', defaults to 'day'.
526
- *
527
- * @return bool|string Returns the fetched data.
528
- *
529
- * @api
530
- */
531
- public function getRawUVIndexData ($ lat , $ lon , $ dateTime , $ timePrecision = 'day ' )
532
- {
533
- if (!$ this ->apiKey ) {
534
- throw new \RuntimeException ('Before using this method, you must set the api key using ->setApiKey() ' );
542
+ if (isset ($ cnt ) && (!is_int ($ cnt ) || $ cnt > 8 || $ cnt < 1 )) {
543
+ throw new \InvalidArgumentException ('$cnt must be an int between 1 and 8 ' );
535
544
}
536
- if (!is_float ($ lat ) || !is_float ($ lon )) {
537
- throw new \InvalidArgumentException ('$lat and $lon must be floating point numbers ' );
545
+ if (isset ($ start ) && !$ start instanceof \DateTime) {
546
+ throw new \InvalidArgumentException ('$start must be an instance of \DateTime ' );
547
+ }
548
+ if (isset ($ end ) && !$ end instanceof \DateTime) {
549
+ throw new \InvalidArgumentException ('$end must be an instance of \DateTime ' );
538
550
}
539
- if (interface_exists ('DateTimeInterface ' ) && !$ dateTime instanceof \DateTimeInterface || !$ dateTime instanceof \DateTime) {
540
- throw new \InvalidArgumentException ('$dateTime must be an instance of \DateTime or \DateTimeInterface ' );
551
+ if ($ mode === 'current ' && (isset ($ start ) || isset ($ end ) || isset ($ cnt ))) {
552
+ throw new \InvalidArgumentException ('Neither $start, $end, nor $cnt must be set for current data. ' );
553
+ } elseif ($ mode === 'forecast ' && (isset ($ start ) || isset ($ end ) || !isset ($ cnt ))) {
554
+ throw new \InvalidArgumentException ('$cnt needs to be set and both $start and $end must not be set for forecast data. ' );
555
+ } elseif ($ mode === 'historic ' && (!isset ($ start ) || !isset ($ end ) || isset ($ cnt ))) {
556
+ throw new \InvalidArgumentException ('Both $start and $end need to be set and $cnt must not be set for historic data. ' );
541
557
}
542
- $ url = $ this ->buildUVIndexUrl ($ lat , $ lon , $ dateTime , $ timePrecision );
543
558
559
+ $ url = $ this ->buildUVIndexUrl ($ mode , $ lat , $ lon , $ cnt , $ start , $ end );
544
560
return $ this ->cacheOrFetchResult ($ url );
545
561
}
546
562
@@ -575,10 +591,12 @@ private function cacheOrFetchResult($url)
575
591
/** @var AbstractCache $cache */
576
592
$ cache = $ this ->cache ;
577
593
$ cache ->setSeconds ($ this ->seconds );
594
+
578
595
if ($ cache ->isCached ($ url )) {
579
596
$ this ->wasCached = true ;
580
597
return $ cache ->getCached ($ url );
581
598
}
599
+
582
600
$ result = $ this ->fetcher ->fetch ($ url );
583
601
$ cache ->setCached ($ url , $ result );
584
602
} else {
@@ -612,47 +630,41 @@ private function buildUrl($query, $units, $lang, $appid, $mode, $url)
612
630
}
613
631
614
632
/**
615
- * @param float $lat
616
- * @param float $lon
617
- * @param \DateTime|\DateTimeImmutable $dateTime
618
- * @param string $timePrecision
633
+ * @param string $mode The type of requested data.
634
+ * @param float $lat The location's latitude.
635
+ * @param float $lon The location's longitude.
636
+ * @param int $cnt Number of returned days.
637
+ * @param \DateTime $start Starting point of time period.
638
+ * @param \DateTime $end Final point of time period.
619
639
*
620
640
* @return string
621
641
*/
622
- private function buildUVIndexUrl ($ lat , $ lon , $ dateTime = null , $ timePrecision = null )
642
+ private function buildUVIndexUrl ($ mode , $ lat , $ lon , $ cnt = null , \ DateTime $ start = null , \ DateTime $ end = null )
623
643
{
624
- if ($ dateTime !== null ) {
625
- $ format = '\Z ' ;
626
- switch ($ timePrecision ) {
627
- /** @noinspection PhpMissingBreakStatementInspection */
628
- case 'second ' :
629
- $ format = ':s ' . $ format ;
630
- /** @noinspection PhpMissingBreakStatementInspection */
631
- case 'minute ' :
632
- $ format = ':i ' . $ format ;
633
- /** @noinspection PhpMissingBreakStatementInspection */
634
- case 'hour ' :
635
- $ format = '\TH ' . $ format ;
636
- /** @noinspection PhpMissingBreakStatementInspection */
637
- case 'day ' :
638
- $ format = '-d ' . $ format ;
639
- /** @noinspection PhpMissingBreakStatementInspection */
640
- case 'month ' :
641
- $ format = '-m ' . $ format ;
642
- case 'year ' :
643
- $ format = 'Y ' . $ format ;
644
- break ;
645
- default :
646
- throw new \InvalidArgumentException ('$timePrecision is invalid. ' );
647
- }
648
- // OWM only accepts UTC timezones.
649
- $ dateTime ->setTimezone (new \DateTimeZone ('UTC ' ));
650
- $ dateTime = $ dateTime ->format ($ format );
651
- } else {
652
- $ dateTime = 'current ' ;
644
+ $ params = array (
645
+ 'appid ' => $ this ->apiKey ,
646
+ 'lat ' => $ lat ,
647
+ 'lon ' => $ lon ,
648
+ );
649
+
650
+ switch ($ mode ) {
651
+ case 'historic ' :
652
+ $ requestMode = '/history ' ;
653
+ $ params ['start ' ] = $ start ->format ('U ' );
654
+ $ params ['end ' ] = $ end ->format ('U ' );
655
+ break ;
656
+ case 'forecast ' :
657
+ $ requestMode = '/forecast ' ;
658
+ $ params ['cnt ' ] = $ cnt ;
659
+ break ;
660
+ case 'current ' :
661
+ $ requestMode = '' ;
662
+ break ;
663
+ default :
664
+ throw new \InvalidArgumentException ("Invalid mode $ mode for uv index url " );
653
665
}
654
666
655
- return sprintf ($ this ->uvIndexUrl . '/%s,%s/%s.json?appid= %s ' , $ lat , $ lon , $ dateTime , $ this -> apiKey );
667
+ return sprintf ($ this ->uvIndexUrl . '%s? %s ' , $ requestMode , http_build_query ( $ params ) );
656
668
}
657
669
658
670
/**
@@ -718,7 +730,8 @@ private function parseJson($answer)
718
730
{
719
731
$ json = json_decode ($ answer );
720
732
if (json_last_error () !== JSON_ERROR_NONE ) {
721
- throw new OWMException ('OpenWeatherMap returned an invalid json object. JSON error was: ' . $ this ->json_last_error_msg ());
733
+ throw new OWMException ('OpenWeatherMap returned an invalid json object. JSON error was: " ' .
734
+ $ this ->json_last_error_msg () . '". The retrieved json was: ' . $ answer );
722
735
}
723
736
if (isset ($ json ->message )) {
724
737
throw new OWMException ('An error occurred: ' . $ json ->message );
0 commit comments