1
1
<?php
2
- /**
3
- * OpenWeatherMap-PHP-API — A php api to parse weather data from http://www.OpenWeatherMap.org .
2
+
3
+ /*
4
+ * OpenWeatherMap-PHP-API — A PHP API to parse weather data from https://OpenWeatherMap.org.
4
5
*
5
6
* @license MIT
6
7
*
7
8
* Please see the LICENSE file distributed with this source code for further
8
9
* information regarding copyright and licensing.
9
10
*
10
11
* Please visit the following links to read about the usage policies and the license of
11
- * OpenWeatherMap before using this class :
12
+ * OpenWeatherMap data before using this library :
12
13
*
13
- * @see http ://www. OpenWeatherMap.org
14
- * @see http ://www. OpenWeatherMap.org/terms
15
- * @see http ://openweathermap .org/appid
14
+ * @see https ://OpenWeatherMap.org/price
15
+ * @see https ://OpenWeatherMap.org/terms
16
+ * @see https ://OpenWeatherMap .org/appid
16
17
*/
17
18
18
19
namespace Cmfcmf ;
19
20
20
- use Cmfcmf \OpenWeatherMap \AbstractCache ;
21
21
use Cmfcmf \OpenWeatherMap \CurrentWeather ;
22
22
use Cmfcmf \OpenWeatherMap \UVIndex ;
23
23
use Cmfcmf \OpenWeatherMap \CurrentWeatherGroup ;
24
24
use Cmfcmf \OpenWeatherMap \Exception as OWMException ;
25
- use Cmfcmf \OpenWeatherMap \Fetcher \CurlFetcher ;
26
- use Cmfcmf \OpenWeatherMap \Fetcher \FetcherInterface ;
27
- use Cmfcmf \OpenWeatherMap \Fetcher \FileGetContentsFetcher ;
28
25
use Cmfcmf \OpenWeatherMap \WeatherForecast ;
29
- use Cmfcmf \OpenWeatherMap \WeatherHistory ;
26
+ use Psr \Cache \CacheItemPoolInterface ;
27
+ use Psr \Http \Client \ClientInterface ;
28
+ use Psr \Http \Message \RequestFactoryInterface ;
30
29
31
30
/**
32
31
* Main class for the OpenWeatherMap-PHP-API. Only use this class.
@@ -63,35 +62,35 @@ class OpenWeatherMap
63
62
*/
64
63
private $ weatherDailyForecastUrl = 'https://api.openweathermap.org/data/2.5/forecast/daily? ' ;
65
64
66
- /**
67
- * @var string The basic api url to fetch history weather data from.
68
- */
69
- private $ weatherHistoryUrl = 'https://history.openweathermap.org/data/2.5/history/city? ' ;
70
-
71
65
/**
72
66
* @var string The basic api url to fetch uv index data from.
73
67
*/
74
68
private $ uvIndexUrl = 'https://api.openweathermap.org/data/2.5/uvi ' ;
75
69
76
70
/**
77
- * @var AbstractCache|bool $cache The cache to use.
71
+ * @var CacheItemPoolInterface|null $cache The cache to use.
78
72
*/
79
- private $ cache = false ;
73
+ private $ cache = null ;
80
74
81
75
/**
82
76
* @var int
83
77
*/
84
- private $ seconds ;
78
+ private $ ttl ;
85
79
86
80
/**
87
81
* @var bool
88
82
*/
89
83
private $ wasCached = false ;
90
84
91
85
/**
92
- * @var FetcherInterface The url fetcher.
86
+ * @var ClientInterface
87
+ */
88
+ private $ httpClient ;
89
+
90
+ /**
91
+ * @var RequestFactoryInterface
93
92
*/
94
- private $ fetcher ;
93
+ private $ httpRequestFactory ;
95
94
96
95
/**
97
96
* @var string
@@ -101,45 +100,31 @@ class OpenWeatherMap
101
100
/**
102
101
* Constructs the OpenWeatherMap object.
103
102
*
104
- * @param string $apiKey The OpenWeatherMap API key. Required and only optional for BC.
105
- * @param null|FetcherInterface $fetcher The interface to fetch the data from OpenWeatherMap. Defaults to
106
- * CurlFetcher() if cURL is available. Otherwise defaults to
107
- * FileGetContentsFetcher() using 'file_get_contents()'.
108
- * @param bool|string $cache If set to false, caching is disabled. Otherwise this must be a class
109
- * extending AbstractCache. Defaults to false.
110
- * @param int $seconds How long weather data shall be cached. Default 10 minutes.
111
- *
112
- * @throws \Exception If $cache is neither false nor a valid callable extending Cmfcmf\OpenWeatherMap\Util\Cache.
103
+ * @param string $apiKey The OpenWeatherMap API key. Required.
104
+ * @param ClientInterface $httpClient A PSR-18 compatible HTTP client implementation.
105
+ * @param RequestFactoryInterface $httpRequestFactory A PSR-17 compatbile HTTP request factory implementation.
106
+ * @param null|CacheItemPoolInterface $cache If set to null, caching is disabled. Otherwise this must be
107
+ * a PSR-6 compatible cache instance.
108
+ * @param int $ttl How long weather data shall be cached. Defaults to 10 minutes.
109
+ * Only used if $cache is not null.
113
110
*
114
111
* @api
115
112
*/
116
- public function __construct ($ apiKey = '' , $ fetcher = null , $ cache = false , $ seconds = 600 )
113
+ public function __construct ($ apiKey , $ httpClient , $ httpRequestFactory , $ cache = null , $ ttl = 600 )
117
114
{
118
115
if (!is_string ($ apiKey ) || empty ($ apiKey )) {
119
- // BC
120
- $ seconds = $ cache !== false ? $ cache : 600 ;
121
- $ cache = $ fetcher !== null ? $ fetcher : false ;
122
- $ fetcher = $ apiKey !== '' ? $ apiKey : null ;
123
- } else {
124
- $ this ->apiKey = $ apiKey ;
116
+ throw new \InvalidArgumentException ("You must provide an API key. " );
125
117
}
126
118
127
- if ($ cache !== false && !($ cache instanceof AbstractCache)) {
128
- throw new \InvalidArgumentException ('The cache class must implement the FetcherInterface! ' );
129
- }
130
- if (!is_numeric ($ seconds )) {
131
- throw new \InvalidArgumentException ('$seconds must be numeric. ' );
132
- }
133
- if (!isset ($ fetcher )) {
134
- $ fetcher = (function_exists ('curl_version ' )) ? new CurlFetcher () : new FileGetContentsFetcher ();
135
- }
136
- if ($ seconds == 0 ) {
137
- $ cache = false ;
119
+ if (!is_numeric ($ ttl )) {
120
+ throw new \InvalidArgumentException ('$ttl must be numeric. ' );
138
121
}
139
122
123
+ $ this ->apiKey = $ apiKey ;
124
+ $ this ->httpClient = $ httpClient ;
125
+ $ this ->httpRequestFactory = $ httpRequestFactory ;
140
126
$ this ->cache = $ cache ;
141
- $ this ->seconds = $ seconds ;
142
- $ this ->fetcher = $ fetcher ;
127
+ $ this ->ttl = $ ttl ;
143
128
}
144
129
145
130
/**
@@ -279,39 +264,6 @@ public function getDailyWeatherForecast($query, $units = 'imperial', $lang = 'en
279
264
return new WeatherForecast ($ xml , $ units , $ days );
280
265
}
281
266
282
- /**
283
- * Returns the weather history for the place you specified.
284
- *
285
- * @param array|int|string $query The place to get weather information for. For possible values see ::getWeather.
286
- * @param \DateTime $start
287
- * @param int $endOrCount
288
- * @param string $type Can either be 'tick', 'hour' or 'day'.
289
- * @param string $units Can be either 'metric' or 'imperial' (default). This affects almost all units returned.
290
- * @param string $lang The language to use for descriptions, default is 'en'. For possible values see http://openweathermap.org/current#multi.
291
- * @param string $appid Your app id, default ''. See http://openweathermap.org/appid for more details.
292
- *
293
- * @throws OpenWeatherMap\Exception If OpenWeatherMap returns an error.
294
- * @throws \InvalidArgumentException If an argument error occurs.
295
- *
296
- * @return WeatherHistory
297
- *
298
- * @api
299
- */
300
- public function getWeatherHistory ($ query , \DateTime $ start , $ endOrCount = 1 , $ type = 'hour ' , $ units = 'imperial ' , $ lang = 'en ' , $ appid = '' )
301
- {
302
- if (!in_array ($ type , array ('tick ' , 'hour ' , 'day ' ))) {
303
- throw new \InvalidArgumentException ('$type must be either "tick", "hour" or "day" ' );
304
- }
305
-
306
- $ xml = json_decode ($ this ->getRawWeatherHistory ($ query , $ start , $ endOrCount , $ type , $ units , $ lang , $ appid ), true );
307
-
308
- if ($ xml ['cod ' ] != 200 ) {
309
- throw new OWMException ($ xml ['message ' ], $ xml ['cod ' ]);
310
- }
311
-
312
- return new WeatherHistory ($ xml , $ query );
313
- }
314
-
315
267
/**
316
268
* Returns the current uv index at the location you specified.
317
269
*
@@ -476,47 +428,6 @@ public function getRawDailyForecastData($query, $units = 'imperial', $lang = 'en
476
428
return $ this ->cacheOrFetchResult ($ url );
477
429
}
478
430
479
- /**
480
- * Directly returns the json string returned by OpenWeatherMap for the weather history.
481
- *
482
- * @param array|int|string $query The place to get weather information for. For possible values see ::getWeather.
483
- * @param \DateTime $start The \DateTime object of the date to get the first weather information from.
484
- * @param \DateTime|int $endOrCount Can be either a \DateTime object representing the end of the period to
485
- * receive weather history data for or an integer counting the number of
486
- * reports requested.
487
- * @param string $type The period of the weather history requested. Can be either be either "tick",
488
- * "hour" or "day".
489
- * @param string $units Can be either 'metric' or 'imperial' (default). This affects almost all units returned.
490
- * @param string $lang The language to use for descriptions, default is 'en'. For possible values see http://openweathermap.org/current#multi.
491
- * @param string $appid Your app id, default ''. See http://openweathermap.org/appid for more details.
492
- *
493
- * @throws \InvalidArgumentException
494
- *
495
- * @return string Returns false on failure and the fetched data in the format you specified on success.
496
- *
497
- * Warning If an error occurred, OpenWeatherMap ALWAYS returns data in json format.
498
- *
499
- * @api
500
- */
501
- public function getRawWeatherHistory ($ query , \DateTime $ start , $ endOrCount = 1 , $ type = 'hour ' , $ units = 'imperial ' , $ lang = 'en ' , $ appid = '' )
502
- {
503
- if (!in_array ($ type , array ('tick ' , 'hour ' , 'day ' ))) {
504
- throw new \InvalidArgumentException ('$type must be either "tick", "hour" or "day" ' );
505
- }
506
-
507
- $ url = $ this ->buildUrl ($ query , $ units , $ lang , $ appid , 'json ' , $ this ->weatherHistoryUrl );
508
- $ url .= "&type= $ type&start= {$ start ->format ('U ' )}" ;
509
- if ($ endOrCount instanceof \DateTime) {
510
- $ url .= "&end= {$ endOrCount ->format ('U ' )}" ;
511
- } elseif (is_numeric ($ endOrCount ) && $ endOrCount > 0 ) {
512
- $ url .= "&cnt= $ endOrCount " ;
513
- } else {
514
- throw new \InvalidArgumentException ('$endOrCount must be either a \DateTime or a positive integer. ' );
515
- }
516
-
517
- return $ this ->cacheOrFetchResult ($ url );
518
- }
519
-
520
431
/**
521
432
* Directly returns the json string returned by OpenWeatherMap for the UV index data.
522
433
*
@@ -570,14 +481,6 @@ public function wasCached()
570
481
return $ this ->wasCached ;
571
482
}
572
483
573
- /**
574
- * @deprecated Use {@link self::getRawWeatherData()} instead.
575
- */
576
- public function getRawData ($ query , $ units = 'imperial ' , $ lang = 'en ' , $ appid = '' , $ mode = 'xml ' )
577
- {
578
- return $ this ->getRawWeatherData ($ query , $ units , $ lang , $ appid , $ mode );
579
- }
580
-
581
484
/**
582
485
* Fetches the result or delivers a cached version of the result.
583
486
*
@@ -587,20 +490,28 @@ public function getRawData($query, $units = 'imperial', $lang = 'en', $appid = '
587
490
*/
588
491
private function cacheOrFetchResult ($ url )
589
492
{
590
- if ($ this ->cache !== false ) {
591
- /** @var AbstractCache $cache */
592
- $ cache = $ this ->cache ;
593
- $ cache ->setSeconds ($ this ->seconds );
594
-
595
- if ($ cache ->isCached ($ url )) {
493
+ if ($ this ->cache !== null ) {
494
+ $ key = str_replace (
495
+ ["{ " , "} " , "( " , ") " , "/ " , "\\" , "@ " , ": " ],
496
+ ["_ " , "_ " , "_ " , "_ " , "_ " , "_ " , "_ " , "_ " ],
497
+ $ url );
498
+ $ item = $ this ->cache ->getItem ($ key );
499
+ if ($ item ->isHit ()) {
596
500
$ this ->wasCached = true ;
597
- return $ cache -> getCached ( $ url );
501
+ return $ item -> get ( );
598
502
}
503
+ }
599
504
600
- $ result = $ this ->fetcher ->fetch ($ url );
601
- $ cache ->setCached ($ url , $ result );
602
- } else {
603
- $ result = $ this ->fetcher ->fetch ($ url );
505
+ $ response = $ this ->httpClient ->sendRequest ($ this ->httpRequestFactory ->createRequest ("GET " , $ url ));
506
+ $ result = $ response ->getBody ()->getContents ();
507
+ if ($ response ->getStatusCode () !== 200 ) {
508
+ throw new OWMException ('OpenWeatherMap returned a response with status code ' . $ response ->getStatusCode () . ' and the following content ' . $ result );
509
+ }
510
+
511
+ if ($ this ->cache !== null ) {
512
+ $ item ->set ($ result );
513
+ $ item ->expiresAfter ($ this ->ttl );
514
+ $ this ->cache ->save ($ item );
604
515
}
605
516
$ this ->wasCached = false ;
606
517
@@ -723,7 +634,7 @@ private function parseXML($answer)
723
634
/**
724
635
* @param string $answer The content returned by OpenWeatherMap.
725
636
*
726
- * @return \stdClass
637
+ * @return \stdClass|array
727
638
* @throws OWMException If the content isn't valid JSON.
728
639
*/
729
640
private function parseJson ($ answer )
0 commit comments