From b379cb9d524332d7044514de5b3dd25f52545472 Mon Sep 17 00:00:00 2001 From: Roel van Hintum Date: Wed, 10 Apr 2019 15:56:51 +0200 Subject: [PATCH 01/12] Updated the UVIndex implementation --- Cmfcmf/OpenWeatherMap.php | 175 ++++++++++++++++-------------- Cmfcmf/OpenWeatherMap/UVIndex.php | 6 +- 2 files changed, 97 insertions(+), 84 deletions(-) diff --git a/Cmfcmf/OpenWeatherMap.php b/Cmfcmf/OpenWeatherMap.php index 500dfa7..c4cfeba 100644 --- a/Cmfcmf/OpenWeatherMap.php +++ b/Cmfcmf/OpenWeatherMap.php @@ -71,7 +71,7 @@ class OpenWeatherMap /** * @var string The basic api url to fetch uv index data from. */ - private $uvIndexUrl = 'https://api.openweathermap.org/v3/uvi'; + private $uvIndexUrl = 'https://api.openweathermap.org/data/2.5/uvi'; /** * @var AbstractCache|bool $cache The cache to use. @@ -327,21 +327,18 @@ public function getWeatherHistory($query, \DateTime $start, $endOrCount = 1, $ty */ public function getCurrentUVIndex($lat, $lon) { - $answer = $this->getRawCurrentUVIndexData($lat, $lon); + $answer = $this->getRawUVIndexData('current', $lat, $lon); $json = $this->parseJson($answer); return new UVIndex($json); } /** - * Returns the uv index at date, time and location you specified. + * Returns the current uv index at the location you specified. * * @param float $lat The location's latitude. * @param float $lon The location's longitude. - * @param \DateTimeInterface $dateTime The date and time to request data for. - * @param string $timePrecision This decides about the timespan OWM will look for the uv index. The tighter - * the timespan, the less likely it is to get a result. Can be 'year', 'month', - * 'day', 'hour', 'minute' or 'second', defaults to 'day'. + * @param int $cnt Number of returned days. * * @throws OpenWeatherMap\Exception If OpenWeatherMap returns an error. * @throws \InvalidArgumentException If an argument error occurs. @@ -350,12 +347,44 @@ public function getCurrentUVIndex($lat, $lon) * * @api */ - public function getUVIndex($lat, $lon, $dateTime, $timePrecision = 'day') + public function getForecastUVIndex($lat, $lon, $cnt) { - $answer = $this->getRawUVIndexData($lat, $lon, $dateTime, $timePrecision); - $json = $this->parseJson($answer); + $answer = $this->getRawUVIndexData('forecast', $lat, $lon, $cnt); + $data = $this->parseJson($answer); - return new UVIndex($json); + $mapData = function ($entry) { + return new UVIndex($entry); + }; + + return array_map($mapData, $data); + } + + /** + * Returns the current uv index at the location you specified. + * + * @param float $lat The location's latitude. + * @param float $lon The location's longitude. + * @param int $cnt Number of returned days. + * @param \DateTime $start Starting point of time period. + * @param \DateTime $end Final point of time period. + * + * @throws OpenWeatherMap\Exception If OpenWeatherMap returns an error. + * @throws \InvalidArgumentException If an argument error occurs. + * + * @return UVIndex The uvi object. + * + * @api + */ + public function getHistoryUVIndex($lat, $lon, $cnt, $start, $end) + { + $answer = $this->getRawUVIndexData('history', $lat, $lon, $cnt, $start, $end); + $data = $this->parseJson($answer); + + $mapData = function ($entry) { + return new UVIndex($entry); + }; + + return array_map($mapData, $data); } /** @@ -492,54 +521,35 @@ public function getRawWeatherHistory($query, \DateTime $start, $endOrCount = 1, } /** - * Directly returns the json string returned by OpenWeatherMap for the current UV index data. + * Directly returns the json string returned by OpenWeatherMap for the UV index data. * - * @param float $lat The location's latitude. - * @param float $lon The location's longitude. + * @param string $mode The type of requested data. + * @param float $lat The location's latitude. + * @param float $lon The location's longitude. + * @param int $cnt Number of returned days. + * @param \DateTime $start Starting point of time period. + * @param \DateTime $end Final point of time period. * * @return bool|string Returns the fetched data. * * @api */ - public function getRawCurrentUVIndexData($lat, $lon) + public function getRawUVIndexData($mode, $lat, $lon, $cnt = null, $start = null, $end = null) { - if (!$this->apiKey) { - throw new \RuntimeException('Before using this method, you must set the api key using ->setApiKey()'); - } if (!is_float($lat) || !is_float($lon)) { throw new \InvalidArgumentException('$lat and $lon must be floating point numbers'); } - $url = $this->buildUVIndexUrl($lat, $lon); - - return $this->cacheOrFetchResult($url); - } - - /** - * Directly returns the json string returned by OpenWeatherMap for the UV index data. - * - * @param float $lat The location's latitude. - * @param float $lon The location's longitude. - * @param \DateTimeInterface $dateTime The date and time to request data for. - * @param string $timePrecision This decides about the timespan OWM will look for the uv index. The tighter - * the timespan, the less likely it is to get a result. Can be 'year', 'month', - * 'day', 'hour', 'minute' or 'second', defaults to 'day'. - * - * @return bool|string Returns the fetched data. - * - * @api - */ - public function getRawUVIndexData($lat, $lon, $dateTime, $timePrecision = 'day') - { - if (!$this->apiKey) { - throw new \RuntimeException('Before using this method, you must set the api key using ->setApiKey()'); + if (isset($cnt) && !is_int($cnt)) { + throw new \InvalidArgumentException('$cnt must be an int'); } - if (!is_float($lat) || !is_float($lon)) { - throw new \InvalidArgumentException('$lat and $lon must be floating point numbers'); + if (isset($start) && !$start instanceof \DateTime) { + throw new \InvalidArgumentException('$start must be an instance of \DateTime'); } - if (interface_exists('DateTimeInterface') && !$dateTime instanceof \DateTimeInterface || !$dateTime instanceof \DateTime) { - throw new \InvalidArgumentException('$dateTime must be an instance of \DateTime or \DateTimeInterface'); + if (isset($end) && !$end instanceof \DateTime) { + throw new \InvalidArgumentException('$end must be an instance of \DateTime'); } - $url = $this->buildUVIndexUrl($lat, $lon, $dateTime, $timePrecision); + + $url = $this->buildUVIndexUrl($mode, $lat, $lon, $cnt, $start, $end); return $this->cacheOrFetchResult($url); } @@ -575,10 +585,12 @@ private function cacheOrFetchResult($url) /** @var AbstractCache $cache */ $cache = $this->cache; $cache->setSeconds($this->seconds); + if ($cache->isCached($url)) { $this->wasCached = true; return $cache->getCached($url); } + $result = $this->fetcher->fetch($url); $cache->setCached($url, $result); } else { @@ -612,47 +624,48 @@ private function buildUrl($query, $units, $lang, $appid, $mode, $url) } /** - * @param float $lat - * @param float $lon - * @param \DateTime|\DateTimeImmutable $dateTime - * @param string $timePrecision + * @param string $mode The type of requested data. + * @param float $lat The location's latitude. + * @param float $lon The location's longitude. + * @param int $cnt Number of returned days. + * @param \DateTime $start Starting point of time period. + * @param \DateTime $end Final point of time period. * * @return string */ - private function buildUVIndexUrl($lat, $lon, $dateTime = null, $timePrecision = null) + private function buildUVIndexUrl($mode, $lat, $lon, $cnt = null, \DateTime $start = null, \DateTime $end = null) { - if ($dateTime !== null) { - $format = '\Z'; - switch ($timePrecision) { - /** @noinspection PhpMissingBreakStatementInspection */ - case 'second': - $format = ':s' . $format; - /** @noinspection PhpMissingBreakStatementInspection */ - case 'minute': - $format = ':i' . $format; - /** @noinspection PhpMissingBreakStatementInspection */ - case 'hour': - $format = '\TH' . $format; - /** @noinspection PhpMissingBreakStatementInspection */ - case 'day': - $format = '-d' . $format; - /** @noinspection PhpMissingBreakStatementInspection */ - case 'month': - $format = '-m' . $format; - case 'year': - $format = 'Y' . $format; - break; - default: - throw new \InvalidArgumentException('$timePrecision is invalid.'); - } - // OWM only accepts UTC timezones. - $dateTime->setTimezone(new \DateTimeZone('UTC')); - $dateTime = $dateTime->format($format); - } else { - $dateTime = 'current'; + switch ($mode) { + case 'history': + $requestMode = '/history'; + break; + case 'forecast': + $requestMode = '/forecast'; + break; + case 'current': + default: + $requestMode = ''; + } + + $params = [ + 'appid' => $this->apiKey, + 'lat' => $lat, + 'lon' => $lon, + ]; + + if (!is_int($cnt)) { + $params['cnt'] = $cnt; + } + + if (!is_int($start)) { + $params['start'] = $start; + } + + if (!is_int($end)) { + $params['end'] = $end; } - return sprintf($this->uvIndexUrl . '/%s,%s/%s.json?appid=%s', $lat, $lon, $dateTime, $this->apiKey); + return sprintf($this->uvIndexUrl . '%s?%s', $requestMode, http_build_query($params)); } /** diff --git a/Cmfcmf/OpenWeatherMap/UVIndex.php b/Cmfcmf/OpenWeatherMap/UVIndex.php index b89d109..928bd17 100644 --- a/Cmfcmf/OpenWeatherMap/UVIndex.php +++ b/Cmfcmf/OpenWeatherMap/UVIndex.php @@ -49,8 +49,8 @@ class UVIndex public function __construct($data) { $utctz = new \DateTimeZone('UTC'); - $this->time = new \DateTime($data->time, $utctz); - $this->location = new Location($data->location->latitude, $data->location->longitude); - $this->uvIndex = (float)$data->data; + $this->time = new \DateTime($data->date_iso, $utctz); + $this->location = new Location($data->lat, $data->lon); + $this->uvIndex = (float)$data->value; } } From 8e5532352f5398675fb3f5402469ab63b1cbec88 Mon Sep 17 00:00:00 2001 From: Roel van Hintum Date: Tue, 7 May 2019 09:21:36 +0200 Subject: [PATCH 02/12] Added UVIndex tests. --- Cmfcmf/OpenWeatherMap.php | 4 +- .../OpenWeatherMapExceptionTest.php | 44 +++++-------------- tests/OpenWeatherMapTest.php | 23 ++++++++-- 3 files changed, 31 insertions(+), 40 deletions(-) diff --git a/Cmfcmf/OpenWeatherMap.php b/Cmfcmf/OpenWeatherMap.php index c4cfeba..9e1ea57 100644 --- a/Cmfcmf/OpenWeatherMap.php +++ b/Cmfcmf/OpenWeatherMap.php @@ -343,7 +343,7 @@ public function getCurrentUVIndex($lat, $lon) * @throws OpenWeatherMap\Exception If OpenWeatherMap returns an error. * @throws \InvalidArgumentException If an argument error occurs. * - * @return UVIndex The uvi object. + * @return array of UVIndex The uvi object. * * @api */ @@ -371,7 +371,7 @@ public function getForecastUVIndex($lat, $lon, $cnt) * @throws OpenWeatherMap\Exception If OpenWeatherMap returns an error. * @throws \InvalidArgumentException If an argument error occurs. * - * @return UVIndex The uvi object. + * @return array of UVIndex The uvi object. * * @api */ diff --git a/tests/Exceptions/OpenWeatherMapExceptionTest.php b/tests/Exceptions/OpenWeatherMapExceptionTest.php index cb195bd..0c48945 100644 --- a/tests/Exceptions/OpenWeatherMapExceptionTest.php +++ b/tests/Exceptions/OpenWeatherMapExceptionTest.php @@ -121,18 +121,9 @@ public function testGetRawWeatherHistoryWithEndDateException() * @expectedException \InvalidArgumentException * @dataProvider uvIndexExceptionDataProvider */ - public function testGetRawUVIndexWithQueryErrorException($lat, $lon, $dateTime, $precision) + public function testGetRawUVIndexWithQueryErrorException($mode, $lat, $lon, $cnt, $start, $end) { - $this->owm->getRawUVIndexData($lat, $lon, $dateTime, $precision); - } - - /** - * @expectedException \InvalidArgumentException - * @dataProvider currentUVIndexExceptionDataProvider - */ - public function testGetRawCurrentUVIndexWithQueryErrorException($lat, $lon) - { - $this->owm->getRawCurrentUVIndexData($lat, $lon); + $this->owm->getRawUVIndexData($mode, $lat, $lon, $cnt, $start, $end); } /** @@ -141,16 +132,7 @@ public function testGetRawCurrentUVIndexWithQueryErrorException($lat, $lon) public function testGetRawUVIndexWithoutApiKey() { $this->owm->setApiKey(null); - $this->owm->getRawUVIndexData(1.1, 1.1, new \DateTime()); - } - - /** - * @expectedException \RuntimeException - */ - public function testGetRawCurrentUVIndexWithoutApiKey() - { - $this->owm->setApiKey(null); - $this->owm->getRawCurrentUVIndexData(1.1, 1.1); + $this->owm->getRawUVIndexData('current', 1.1, 1.1); } /** @@ -198,22 +180,16 @@ public function testParseJsonException() $method->invoke($this->owm, $answer); } + /** + * @expectedException \Cmfcmf\OpenWeatherMap\Exception + */ public function uvIndexExceptionDataProvider() { return array( - array('error-query-format', 'foo', new \DateTime(), 'year'), - array(5.4, 1.2, 'foo', 'month'), - array(5.4, 12, 'foo', 'day'), - array(5.4, 1.2, 'foo', 'bar'), - ); - } - - public function currentUVIndexExceptionDataProvider() - { - return array( - array('error-query-format', 'foo'), - array(5.4, 12), - array(5.4, '1.2'), + array('error-query-format', 5.4, 1.2), + array('current', 5.4, 1.2, 'foo'), + array('forecast', 5.4, 12, null, new \DateTime()), + array('history', 5.4, 1.2, null, new \DateTime(), \DateTime('0-0-0')), ); } } diff --git a/tests/OpenWeatherMapTest.php b/tests/OpenWeatherMapTest.php index 6a27acc..e2aebe6 100644 --- a/tests/OpenWeatherMapTest.php +++ b/tests/OpenWeatherMapTest.php @@ -138,18 +138,33 @@ public function testGetCurrentUVIndex() $this->assertInstanceOf('\Cmfcmf\OpenWeatherMap\UVIndex', $result); } - public function testGetUVIndex() + public function testGetForecastUVIndex() { $owm = $this->openWeather; - $precisions = array('year', 'month', 'day', 'hour', 'minute', 'second'); foreach ($precisions as $precision) { try { - $result = $owm->getUVIndex(40.7, -74.2, new \DateTime(), $precision); + $result = $owm->getForecastUVIndex(40.7, -74.2, 5); } catch (Exception $e) { // OWM might not actually have data for the timespan. $this->assertSame('An error occurred: not found', $e->getMessage()); } - $this->assertInstanceOf('\Cmfcmf\OpenWeatherMap\UVIndex', $result); + $this->assertContainsOnlyInstancesOf('\Cmfcmf\OpenWeatherMap\UVIndex', $result); + } + } + + public function testGetHistoryUVIndex() + { + $owm = $this->openWeather; + foreach ($precisions as $precision) { + try { + $start = new \DateTime('1969-08-15'); + $end = new \DateTime('1969-08-18'); + $result = $owm->getForecastUVIndex(40.7, -74.2, null, $start, $end); + } catch (Exception $e) { + // OWM might not actually have data for the timespan. + $this->assertSame('An error occurred: not found', $e->getMessage()); + } + $this->assertContainsOnlyInstancesOf('\Cmfcmf\OpenWeatherMap\UVIndex', $result); } } From 4d1eb0a38a22e4928d4cf694f86a7f9f7b2a5a49 Mon Sep 17 00:00:00 2001 From: Roel van Hintum Date: Tue, 7 May 2019 09:41:09 +0200 Subject: [PATCH 03/12] UVIndex Test error fixes --- .../OpenWeatherMapExceptionTest.php | 8 ++--- tests/OpenWeatherMapTest.php | 34 +++++++++---------- 2 files changed, 20 insertions(+), 22 deletions(-) diff --git a/tests/Exceptions/OpenWeatherMapExceptionTest.php b/tests/Exceptions/OpenWeatherMapExceptionTest.php index 0c48945..f370502 100644 --- a/tests/Exceptions/OpenWeatherMapExceptionTest.php +++ b/tests/Exceptions/OpenWeatherMapExceptionTest.php @@ -186,10 +186,10 @@ public function testParseJsonException() public function uvIndexExceptionDataProvider() { return array( - array('error-query-format', 5.4, 1.2), - array('current', 5.4, 1.2, 'foo'), - array('forecast', 5.4, 12, null, new \DateTime()), - array('history', 5.4, 1.2, null, new \DateTime(), \DateTime('0-0-0')), + array('error-query-format', 5.4, 1.2, null, null, null), + array('current', 5.4, 1.2, 5, null, null), + array('forecast', 5.4, 12.0, null, new \DateTime(), null), + array('history', 5.4, 1.2, null, new \DateTime(), new \DateTime('0-0-0')), ); } } diff --git a/tests/OpenWeatherMapTest.php b/tests/OpenWeatherMapTest.php index e2aebe6..8e893ae 100644 --- a/tests/OpenWeatherMapTest.php +++ b/tests/OpenWeatherMapTest.php @@ -141,31 +141,29 @@ public function testGetCurrentUVIndex() public function testGetForecastUVIndex() { $owm = $this->openWeather; - foreach ($precisions as $precision) { - try { - $result = $owm->getForecastUVIndex(40.7, -74.2, 5); - } catch (Exception $e) { - // OWM might not actually have data for the timespan. - $this->assertSame('An error occurred: not found', $e->getMessage()); - } - $this->assertContainsOnlyInstancesOf('\Cmfcmf\OpenWeatherMap\UVIndex', $result); + + try { + $result = $owm->getForecastUVIndex(40.7, -74.2, 5); + } catch (Exception $e) { + // OWM might not actually have data for the timespan. + $this->assertSame('An error occurred: not found', $e->getMessage()); } + $this->assertContainsOnlyInstancesOf('\Cmfcmf\OpenWeatherMap\UVIndex', $result); } public function testGetHistoryUVIndex() { $owm = $this->openWeather; - foreach ($precisions as $precision) { - try { - $start = new \DateTime('1969-08-15'); - $end = new \DateTime('1969-08-18'); - $result = $owm->getForecastUVIndex(40.7, -74.2, null, $start, $end); - } catch (Exception $e) { - // OWM might not actually have data for the timespan. - $this->assertSame('An error occurred: not found', $e->getMessage()); - } - $this->assertContainsOnlyInstancesOf('\Cmfcmf\OpenWeatherMap\UVIndex', $result); + + try { + $start = new \DateTime('1969-08-15'); + $end = new \DateTime('1969-08-18'); + $result = $owm->getForecastUVIndex(40.7, -74.2, null, $start, $end); + } catch (Exception $e) { + // OWM might not actually have data for the timespan. + $this->assertSame('An error occurred: not found', $e->getMessage()); } + $this->assertContainsOnlyInstancesOf('\Cmfcmf\OpenWeatherMap\UVIndex', $result); } public function testGetDailyWeatherForecast() From 5368d41d82169cc0c8846e1067b2e03436150399 Mon Sep 17 00:00:00 2001 From: Roel van Hintum Date: Tue, 7 May 2019 09:54:01 +0200 Subject: [PATCH 04/12] Update OpenWeatherMapExceptionTest.php --- .../Exceptions/OpenWeatherMapExceptionTest.php | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/tests/Exceptions/OpenWeatherMapExceptionTest.php b/tests/Exceptions/OpenWeatherMapExceptionTest.php index f370502..8c0d104 100644 --- a/tests/Exceptions/OpenWeatherMapExceptionTest.php +++ b/tests/Exceptions/OpenWeatherMapExceptionTest.php @@ -126,15 +126,6 @@ public function testGetRawUVIndexWithQueryErrorException($mode, $lat, $lon, $cnt $this->owm->getRawUVIndexData($mode, $lat, $lon, $cnt, $start, $end); } - /** - * @expectedException \RuntimeException - */ - public function testGetRawUVIndexWithoutApiKey() - { - $this->owm->setApiKey(null); - $this->owm->getRawUVIndexData('current', 1.1, 1.1); - } - /** * @expectedException \InvalidArgumentException */ @@ -186,10 +177,10 @@ public function testParseJsonException() public function uvIndexExceptionDataProvider() { return array( - array('error-query-format', 5.4, 1.2, null, null, null), - array('current', 5.4, 1.2, 5, null, null), - array('forecast', 5.4, 12.0, null, new \DateTime(), null), - array('history', 5.4, 1.2, null, new \DateTime(), new \DateTime('0-0-0')), + array('current', 5.4, 1, 5, null, null), + array('forecast', 5.4, 1.2, '5', null, null), + array('forecast', 5.4, 12.0, null, '2000-1-1', null), + array('history', 5.4, 1.2, null, new \DateTime(), '2000-1-1'), ); } } From 116188fa8ae526f3411233ff26030ce917193a29 Mon Sep 17 00:00:00 2001 From: Roel van Hintum Date: Tue, 7 May 2019 09:58:28 +0200 Subject: [PATCH 05/12] Fixed array for php 5.3 support --- Cmfcmf/OpenWeatherMap.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cmfcmf/OpenWeatherMap.php b/Cmfcmf/OpenWeatherMap.php index 9e1ea57..5024fc1 100644 --- a/Cmfcmf/OpenWeatherMap.php +++ b/Cmfcmf/OpenWeatherMap.php @@ -647,11 +647,11 @@ private function buildUVIndexUrl($mode, $lat, $lon, $cnt = null, \DateTime $star $requestMode = ''; } - $params = [ + $params = array( 'appid' => $this->apiKey, 'lat' => $lat, 'lon' => $lon, - ]; + ); if (!is_int($cnt)) { $params['cnt'] = $cnt; From 1654630c238f8c5933afbbb755d42697f920f110 Mon Sep 17 00:00:00 2001 From: Christian Flach Date: Wed, 8 May 2019 10:43:00 +0200 Subject: [PATCH 06/12] Remove support for hhvm, test PHP 7.3 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 29e9915..fd31dc7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,8 +5,8 @@ language: php matrix: include: - - php: hhvm - php: nightly + - php: 7.3 - php: 7.2 - php: 7.1 - php: 7.0 From 8a27d17b5e9b017b35eb0d572a89da827bfb2941 Mon Sep 17 00:00:00 2001 From: Christian Flach Date: Wed, 29 May 2019 12:33:18 +0200 Subject: [PATCH 07/12] Minor improvements to new UVIndex api --- Cmfcmf/OpenWeatherMap.php | 109 +++++++++++++++++++------------------- 1 file changed, 54 insertions(+), 55 deletions(-) diff --git a/Cmfcmf/OpenWeatherMap.php b/Cmfcmf/OpenWeatherMap.php index 5024fc1..b2d4548 100644 --- a/Cmfcmf/OpenWeatherMap.php +++ b/Cmfcmf/OpenWeatherMap.php @@ -315,13 +315,13 @@ public function getWeatherHistory($query, \DateTime $start, $endOrCount = 1, $ty /** * Returns the current uv index at the location you specified. * - * @param float $lat The location's latitude. - * @param float $lon The location's longitude. + * @param float $lat The location's latitude. + * @param float $lon The location's longitude. * * @throws OpenWeatherMap\Exception If OpenWeatherMap returns an error. * @throws \InvalidArgumentException If an argument error occurs. * - * @return UVIndex The uvi object. + * @return UVIndex * * @api */ @@ -334,57 +334,54 @@ public function getCurrentUVIndex($lat, $lon) } /** - * Returns the current uv index at the location you specified. + * Returns a forecast of the uv index at the specified location. + * The optional $cnt parameter determines the number of days to forecase. + * The maximum supported number of days is 8. * - * @param float $lat The location's latitude. - * @param float $lon The location's longitude. - * @param int $cnt Number of returned days. + * @param float $lat The location's latitude. + * @param float $lon The location's longitude. + * @param int $cnt Number of returned days (default to 8). * * @throws OpenWeatherMap\Exception If OpenWeatherMap returns an error. * @throws \InvalidArgumentException If an argument error occurs. * - * @return array of UVIndex The uvi object. + * @return UVIndex[] * * @api */ - public function getForecastUVIndex($lat, $lon, $cnt) + public function getForecastUVIndex($lat, $lon, $cnt = 8) { $answer = $this->getRawUVIndexData('forecast', $lat, $lon, $cnt); $data = $this->parseJson($answer); - $mapData = function ($entry) { + return array_map(function ($entry) { return new UVIndex($entry); - }; - - return array_map($mapData, $data); + }, $data); } /** - * Returns the current uv index at the location you specified. + * Returns the historic uv index at the specified location. * - * @param float $lat The location's latitude. - * @param float $lon The location's longitude. - * @param int $cnt Number of returned days. - * @param \DateTime $start Starting point of time period. - * @param \DateTime $end Final point of time period. + * @param float $lat The location's latitude. + * @param float $lon The location's longitude. + * @param \DateTime $start Starting point of time period. + * @param \DateTime $end Final point of time period. * * @throws OpenWeatherMap\Exception If OpenWeatherMap returns an error. * @throws \InvalidArgumentException If an argument error occurs. * - * @return array of UVIndex The uvi object. + * @return UVIndex[] * * @api */ - public function getHistoryUVIndex($lat, $lon, $cnt, $start, $end) + public function getHistoricUVIndex($lat, $lon, $start, $end) { - $answer = $this->getRawUVIndexData('history', $lat, $lon, $cnt, $start, $end); + $answer = $this->getRawUVIndexData('historic', $lat, $lon, null, $start, $end); $data = $this->parseJson($answer); - $mapData = function ($entry) { + return array_map(function ($entry) { return new UVIndex($entry); - }; - - return array_map($mapData, $data); + }, $data); } /** @@ -523,12 +520,12 @@ public function getRawWeatherHistory($query, \DateTime $start, $endOrCount = 1, /** * Directly returns the json string returned by OpenWeatherMap for the UV index data. * - * @param string $mode The type of requested data. - * @param float $lat The location's latitude. - * @param float $lon The location's longitude. - * @param int $cnt Number of returned days. - * @param \DateTime $start Starting point of time period. - * @param \DateTime $end Final point of time period. + * @param string $mode The type of requested data (['historic', 'forecast', 'current']). + * @param float $lat The location's latitude. + * @param float $lon The location's longitude. + * @param int $cnt Number of returned days (only allowed for 'forecast' data). + * @param \DateTime $start Starting point of time period (only allowed and required for 'historic' data). + * @param \DateTime $end Final point of time period (only allowed and required for 'historic' data). * * @return bool|string Returns the fetched data. * @@ -536,11 +533,14 @@ public function getRawWeatherHistory($query, \DateTime $start, $endOrCount = 1, */ public function getRawUVIndexData($mode, $lat, $lon, $cnt = null, $start = null, $end = null) { + if (!in_array($mode, ['current', 'forecast', 'historic'], true)) { + throw new \InvalidArgumentException("$mode must be one of 'historic', 'forecast', 'current'."); + } if (!is_float($lat) || !is_float($lon)) { throw new \InvalidArgumentException('$lat and $lon must be floating point numbers'); } - if (isset($cnt) && !is_int($cnt)) { - throw new \InvalidArgumentException('$cnt must be an int'); + if (isset($cnt) && (!is_int($cnt) || $cnt > 8 || $cnt < 1)) { + throw new \InvalidArgumentException('$cnt must be an int between 1 and 8'); } if (isset($start) && !$start instanceof \DateTime) { throw new \InvalidArgumentException('$start must be an instance of \DateTime'); @@ -548,9 +548,15 @@ public function getRawUVIndexData($mode, $lat, $lon, $cnt = null, $start = null, if (isset($end) && !$end instanceof \DateTime) { throw new \InvalidArgumentException('$end must be an instance of \DateTime'); } + if ($mode === 'current' && (isset($start) || isset($end) || isset($cnt))) { + throw new \InvalidArgumentException('Neither $start, $end, nor $cnt must be set for current data.'); + } else if ($mode === 'forecast' && (isset($start) || isset($end) || !isset($cnt))) { + throw new \InvalidArgumentException('$cnt needs to be set and both $start and $end must not be set for forecast data.'); + } else if ($mode === 'historic' && (!isset($start) || !isset($end) || isset($cnt))) { + throw new \InvalidArgumentException('Both $start and $end need to be set and $cnt must not be set for historic data.'); + } $url = $this->buildUVIndexUrl($mode, $lat, $lon, $cnt, $start, $end); - return $this->cacheOrFetchResult($url); } @@ -635,34 +641,27 @@ private function buildUrl($query, $units, $lang, $appid, $mode, $url) */ private function buildUVIndexUrl($mode, $lat, $lon, $cnt = null, \DateTime $start = null, \DateTime $end = null) { + $params = array( + 'appid' => $this->apiKey, + 'lat' => $lat, + 'lon' => $lon, + ); + switch ($mode) { - case 'history': + case 'historic': $requestMode = '/history'; + $params['start'] = $start->format('U'); + $params['end'] = $end->format('U'); break; case 'forecast': $requestMode = '/forecast'; + $params['cnt'] = $cnt; break; case 'current': - default: $requestMode = ''; - } - - $params = array( - 'appid' => $this->apiKey, - 'lat' => $lat, - 'lon' => $lon, - ); - - if (!is_int($cnt)) { - $params['cnt'] = $cnt; - } - - if (!is_int($start)) { - $params['start'] = $start; - } - - if (!is_int($end)) { - $params['end'] = $end; + break; + default: + throw new \InvalidArgumentException("Invalid mode $mode for uv index url"); } return sprintf($this->uvIndexUrl . '%s?%s', $requestMode, http_build_query($params)); From e4c44257b150a2d6c65a96cf62b0362dc7f2b999 Mon Sep 17 00:00:00 2001 From: Christian Flach Date: Wed, 29 May 2019 12:33:47 +0200 Subject: [PATCH 08/12] Add new UVIndex example, improve error handling and CI --- .travis.yml | 10 ++++--- Cmfcmf/OpenWeatherMap.php | 3 +- Examples/UVIndex.php | 63 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+), 5 deletions(-) create mode 100644 Examples/UVIndex.php diff --git a/.travis.yml b/.travis.yml index fd31dc7..f8e3f06 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,12 +19,14 @@ matrix: allow_failures: - php: nightly -install: - - if [[ ! $TRAVIS_PHP_VERSION = hhvm* ]]; then phpenv config-rm xdebug.ini || echo "xdebug not available"; fi - - if [[ ! $TRAVIS_PHP_VERSION = hhvm* ]]; then INI_FILE=~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini; else INI_FILE=/etc/hhvm/php.ini; fi +before_install: + - phpenv config-rm xdebug.ini || echo "xdebug not available" + - INI_FILE=~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini - echo date.timezone = Europe/Berlin >> $INI_FILE - echo memory_limit = -1 >> $INI_FILE - - composer update + +install: + - composer install script: - vendor/bin/phpunit --coverage-text --coverage-clover=coverage.xml diff --git a/Cmfcmf/OpenWeatherMap.php b/Cmfcmf/OpenWeatherMap.php index b2d4548..cce5996 100644 --- a/Cmfcmf/OpenWeatherMap.php +++ b/Cmfcmf/OpenWeatherMap.php @@ -730,7 +730,8 @@ private function parseJson($answer) { $json = json_decode($answer); if (json_last_error() !== JSON_ERROR_NONE) { - throw new OWMException('OpenWeatherMap returned an invalid json object. JSON error was: ' . $this->json_last_error_msg()); + throw new OWMException('OpenWeatherMap returned an invalid json object. JSON error was: "' . + $this->json_last_error_msg() . '". The retrieved json was: ' . $answer); } if (isset($json->message)) { throw new OWMException('An error occurred: '. $json->message); diff --git a/Examples/UVIndex.php b/Examples/UVIndex.php new file mode 100644 index 0000000..6f0d507 --- /dev/null +++ b/Examples/UVIndex.php @@ -0,0 +1,63 @@ +'; +if (php_sapi_name() === 'cli') { + $lf = "\n"; + $cli = true; +} + +// Language of data (try your own language here!): +$lang = 'de'; + +// Units (can be 'metric' or 'imperial' [default]): +$units = 'metric'; + +// Get OpenWeatherMap object. Don't use caching (take a look into Example_Cache.php to see how it works). +$owm = new OpenWeatherMap(); +$owm->setApiKey($myApiKey); + +// Example 1: Get current uv index in Berlin. +$uvIndex = $owm->getCurrentUVIndex(52.520008, 13.404954); +echo "EXAMPLE 1$lf"; + +echo "Current uv index: $uvIndex->uvIndex"; +echo $lf; + +// Example 2: Get uv index forecast in Berlin. +$forecast = $owm->getForecastUVIndex(52.520008, 13.404954); +echo "EXAMPLE 2$lf"; + +foreach ($forecast as $day) { + echo "{$day->time->format('r')} will have an uv index of: $day->uvIndex"; + echo $lf; +} + + +// Example 3: Get historic uv index in Berlin. +$history = $owm->getHistoricUVIndex(52.520008, 13.404954, new DateTime('-4month'), new DateTime('-3month')); +echo "EXAMPLE 3$lf"; + +foreach ($history as $day) { + echo "{$day->time->format('r')} had an uv index of: $day->uvIndex"; + echo $lf; +} From abe21cf8d7afb710024ae0a34a066f30b523bd10 Mon Sep 17 00:00:00 2001 From: Christian Flach Date: Wed, 29 May 2019 12:36:27 +0200 Subject: [PATCH 09/12] Fix CS --- Cmfcmf/OpenWeatherMap.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cmfcmf/OpenWeatherMap.php b/Cmfcmf/OpenWeatherMap.php index cce5996..eb4f1fe 100644 --- a/Cmfcmf/OpenWeatherMap.php +++ b/Cmfcmf/OpenWeatherMap.php @@ -550,9 +550,9 @@ public function getRawUVIndexData($mode, $lat, $lon, $cnt = null, $start = null, } if ($mode === 'current' && (isset($start) || isset($end) || isset($cnt))) { throw new \InvalidArgumentException('Neither $start, $end, nor $cnt must be set for current data.'); - } else if ($mode === 'forecast' && (isset($start) || isset($end) || !isset($cnt))) { + } elseif ($mode === 'forecast' && (isset($start) || isset($end) || !isset($cnt))) { throw new \InvalidArgumentException('$cnt needs to be set and both $start and $end must not be set for forecast data.'); - } else if ($mode === 'historic' && (!isset($start) || !isset($end) || isset($cnt))) { + } elseif ($mode === 'historic' && (!isset($start) || !isset($end) || isset($cnt))) { throw new \InvalidArgumentException('Both $start and $end need to be set and $cnt must not be set for historic data.'); } From 05b4d1c81fcaad2b9ec49663ed81f81aab412037 Mon Sep 17 00:00:00 2001 From: Christian Flach Date: Wed, 29 May 2019 12:44:15 +0200 Subject: [PATCH 10/12] Adjust tests for changes --- tests/Exceptions/OpenWeatherMapExceptionTest.php | 6 +++++- tests/OpenWeatherMapTest.php | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/Exceptions/OpenWeatherMapExceptionTest.php b/tests/Exceptions/OpenWeatherMapExceptionTest.php index 8c0d104..f17ce91 100644 --- a/tests/Exceptions/OpenWeatherMapExceptionTest.php +++ b/tests/Exceptions/OpenWeatherMapExceptionTest.php @@ -179,8 +179,12 @@ public function uvIndexExceptionDataProvider() return array( array('current', 5.4, 1, 5, null, null), array('forecast', 5.4, 1.2, '5', null, null), + array('forecast', 5.4, 1.2, 0, null, null), + array('forecast', 5.4, 1.2, 9, null, null), + array('forecast', 5.4, 1.2, 5, new \DateTime(), new \DateTime()), array('forecast', 5.4, 12.0, null, '2000-1-1', null), - array('history', 5.4, 1.2, null, new \DateTime(), '2000-1-1'), + array('historic', 5.4, 1.2, null, new \DateTime(), '2000-1-1'), + array('historic', 5.4, 1.2, 5, new \DateTime(), new \DateTime()), ); } } diff --git a/tests/OpenWeatherMapTest.php b/tests/OpenWeatherMapTest.php index 8e893ae..ee67c18 100644 --- a/tests/OpenWeatherMapTest.php +++ b/tests/OpenWeatherMapTest.php @@ -158,7 +158,7 @@ public function testGetHistoryUVIndex() try { $start = new \DateTime('1969-08-15'); $end = new \DateTime('1969-08-18'); - $result = $owm->getForecastUVIndex(40.7, -74.2, null, $start, $end); + $result = $owm->getHistoricUVIndex(40.7, -74.2, $start, $end); } catch (Exception $e) { // OWM might not actually have data for the timespan. $this->assertSame('An error occurred: not found', $e->getMessage()); From 10735e1382eb233114991a22eb535461b08fad0b Mon Sep 17 00:00:00 2001 From: Christian Flach Date: Wed, 29 May 2019 12:50:36 +0200 Subject: [PATCH 11/12] Fix travis build --- .travis.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index f8e3f06..7ce60de 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,7 +26,9 @@ before_install: - echo memory_limit = -1 >> $INI_FILE install: - - composer install + # Use composer update instead of composer install to install a working set of + # dependencies on all PHP versions. + - composer update script: - vendor/bin/phpunit --coverage-text --coverage-clover=coverage.xml From c392fd20c139336ccd3444b6df1b9ce0910cc0ed Mon Sep 17 00:00:00 2001 From: Christian Flach Date: Wed, 29 May 2019 13:01:08 +0200 Subject: [PATCH 12/12] PHP 5.3 compat --- Cmfcmf/OpenWeatherMap.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cmfcmf/OpenWeatherMap.php b/Cmfcmf/OpenWeatherMap.php index eb4f1fe..4ff6ccb 100644 --- a/Cmfcmf/OpenWeatherMap.php +++ b/Cmfcmf/OpenWeatherMap.php @@ -533,7 +533,7 @@ public function getRawWeatherHistory($query, \DateTime $start, $endOrCount = 1, */ public function getRawUVIndexData($mode, $lat, $lon, $cnt = null, $start = null, $end = null) { - if (!in_array($mode, ['current', 'forecast', 'historic'], true)) { + if (!in_array($mode, array('current', 'forecast', 'historic'), true)) { throw new \InvalidArgumentException("$mode must be one of 'historic', 'forecast', 'current'."); } if (!is_float($lat) || !is_float($lon)) {