Skip to content

Commit

Permalink
Merge branch 'M2Mobi-group_weather'
Browse files Browse the repository at this point in the history
  • Loading branch information
cmfcmf committed Oct 17, 2016
2 parents c3530d7 + 6c444d7 commit 654211b
Show file tree
Hide file tree
Showing 3 changed files with 198 additions and 15 deletions.
68 changes: 68 additions & 0 deletions Cmfcmf/OpenWeatherMap.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

use Cmfcmf\OpenWeatherMap\AbstractCache;
use Cmfcmf\OpenWeatherMap\CurrentWeather;
use Cmfcmf\OpenWeatherMap\CurrentWeatherGroup;
use Cmfcmf\OpenWeatherMap\Exception as OWMException;
use Cmfcmf\OpenWeatherMap\Fetcher\CurlFetcher;
use Cmfcmf\OpenWeatherMap\Fetcher\FetcherInterface;
Expand Down Expand Up @@ -46,6 +47,11 @@ class OpenWeatherMap
*/
private $weatherUrl = 'http://api.openweathermap.org/data/2.5/weather?';

/**
* @var string The basic api url to fetch weather group data from.
*/
private $weatherGroupUrl = 'http://api.openweathermap.org/data/2.5/group?';

/**
* @var string The basic api url to fetch weekly forecast data from.
*/
Expand Down Expand Up @@ -182,6 +188,29 @@ public function getWeather($query, $units = 'imperial', $lang = 'en', $appid = '
return new CurrentWeather($xml, $units);
}

/**
* Returns the current weather for a group of city ids.
*
* @param array $ids The city ids to get weather information for
* @param string $units Can be either 'metric' or 'imperial' (default). This affects almost all units returned.
* @param string $lang The language to use for descriptions, default is 'en'. For possible values see http://openweathermap.org/current#multi.
* @param string $appid Your app id, default ''. See http://openweathermap.org/appid for more details.
*
* @throws OpenWeatherMap\Exception If OpenWeatherMap returns an error.
* @throws \InvalidArgumentException If an argument error occurs.
*
* @return Array Array of CurrentWeather objects.
*
* @api
*/
public function getWeatherGroup($ids, $units = 'imperial', $lang = 'en', $appid = '')
{
$answer = $this->getRawWeatherGroupData($ids, $units, $lang, $appid);
$json = $this->parseJson($answer);

return new CurrentWeatherGroup($json, $units);
}

/**
* Returns the forecast for the place you specified. DANGER: Might return
* fewer results than requested due to a bug in the OpenWeatherMap API!
Expand Down Expand Up @@ -296,6 +325,26 @@ public function getRawWeatherData($query, $units = 'imperial', $lang = 'en', $ap
return $this->cacheOrFetchResult($url);
}

/**
* Directly returns the JSON string returned by OpenWeatherMap for the group of current weather.
* Only a JSON response format is supported for this webservice.
*
* @param array $ids The city ids to get weather information for
* @param string $units Can be either 'metric' or 'imperial' (default). This affects almost all units returned.
* @param string $lang The language to use for descriptions, default is 'en'. For possible values see http://openweathermap.org/current#multi.
* @param string $appid Your app id, default ''. See http://openweathermap.org/appid for more details.
*
* @return string Returns false on failure and the fetched data in the format you specified on success.
*
* @api
*/
public function getRawWeatherGroupData($ids, $units = 'imperial', $lang = 'en', $appid = '')
{
$url = $this->buildUrl($ids, $units, $lang, $appid, 'json', $this->weatherGroupUrl);

return $this->cacheOrFetchResult($url);
}

/**
* Directly returns the xml/json/html string returned by OpenWeatherMap for the hourly forecast.
*
Expand Down Expand Up @@ -468,6 +517,8 @@ private function buildQueryUrlParameter($query)
switch ($query) {
case is_array($query) && isset($query['lat']) && isset($query['lon']) && is_numeric($query['lat']) && is_numeric($query['lon']):
return "lat={$query['lat']}&lon={$query['lon']}";
case is_array($query) && is_numeric($query[0]):
return 'id='.implode(',', $query);
case is_numeric($query):
return "id=$query";
case is_string($query):
Expand Down Expand Up @@ -501,4 +552,21 @@ private function parseXML($answer)
}
}
}

/**
* @param string $answer The content returned by OpenWeatherMap.
*
* @return \stdClass
* @throws OWMException If the content isn't valid JSON.
*/
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_last_error_msg());
}

return $json;
}

}
50 changes: 35 additions & 15 deletions Cmfcmf/OpenWeatherMap/CurrentWeather.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,31 +87,51 @@ class CurrentWeather
/**
* Create a new weather object.
*
* @param \SimpleXMLElement $xml
* @param string $units
* @param mixed $data
* @param string $units
*
* @internal
*/
public function __construct(\SimpleXMLElement $xml, $units)
public function __construct($data, $units)
{
$this->city = new City($xml->city['id'], $xml->city['name'], $xml->city->coord['lon'], $xml->city->coord['lat'], $xml->city->country);
$this->temperature = new Temperature(new Unit($xml->temperature['value'], $xml->temperature['unit']), new Unit($xml->temperature['min'], $xml->temperature['unit']), new Unit($xml->temperature['max'], $xml->temperature['unit']));
$this->humidity = new Unit($xml->humidity['value'], $xml->humidity['unit']);
$this->pressure = new Unit($xml->pressure['value'], $xml->pressure['unit']);

// This is kind of a hack, because the units are missing in the xml document.
// This is kind of a hack, because the units are missing in the document.
if ($units == 'metric') {
$windSpeedUnit = 'm/s';
} else {
$windSpeedUnit = 'mph';
}
$this->wind = new Wind(new Unit($xml->wind->speed['value'], $windSpeedUnit, $xml->wind->speed['name']), new Unit($xml->wind->direction['value'], $xml->wind->direction['code'], $xml->wind->direction['name']));

$this->clouds = new Unit($xml->clouds['value'], null, $xml->clouds['name']);
$this->precipitation = new Unit($xml->precipitation['value'], $xml->precipitation['unit'], $xml->precipitation['mode']);
$utctz = new \DateTimeZone('UTC');
$this->sun = new Sun(new \DateTime($xml->city->sun['rise'], $utctz), new \DateTime($xml->city->sun['set'], $utctz));
$this->weather = new WeatherObj($xml->weather['number'], $xml->weather['value'], $xml->weather['icon']);
$this->lastUpdate = new \DateTime($xml->lastupdate['value'], $utctz);

if ($data instanceof \SimpleXMLElement) {
$this->city = new City($data->city['id'], $data->city['name'], $data->city->coord['lon'], $data->city->coord['lat'], $data->city->country);
$this->temperature = new Temperature(new Unit($data->temperature['value'], $data->temperature['unit']), new Unit($data->temperature['min'], $data->temperature['unit']), new Unit($data->temperature['max'], $data->temperature['unit']));
$this->humidity = new Unit($data->humidity['value'], $data->humidity['unit']);
$this->pressure = new Unit($data->pressure['value'], $data->pressure['unit']);
$this->wind = new Wind(new Unit($data->wind->speed['value'], $windSpeedUnit, $data->wind->speed['name']), new Unit($data->wind->direction['value'], $data->wind->direction['code'], $data->wind->direction['name']));
$this->clouds = new Unit($data->clouds['value'], null, $data->clouds['name']);
$this->precipitation = new Unit($data->precipitation['value'], $data->precipitation['unit'], $data->precipitation['mode']);
$this->sun = new Sun(new \DateTime($data->city->sun['rise'], $utctz), new \DateTime($data->city->sun['set'], $utctz));
$this->weather = new WeatherObj($data->weather['number'], $data->weather['value'], $data->weather['icon']);
$this->lastUpdate = new \DateTime($data->lastupdate['value'], $utctz);
} else {
$this->city = new City($data->id, $data->name, $data->coord->lon, $data->coord->lat, $data->sys->country);
$this->temperature = new Temperature(new Unit($data->main->temp, $units), new Unit($data->main->temp_min, $units), new Unit($data->main->temp_max, $units));
$this->humidity = new Unit($data->main->humidity, '%');
$this->pressure = new Unit($data->main->pressure, 'hPa');
$this->wind = new Wind(new Unit($data->wind->speed, $windSpeedUnit), new Unit($data->wind->deg));
$this->clouds = new Unit($data->clouds->all, '%');

// the rain field is not always present in the JSON response
// and sometimes it contains the field '1h', sometimes the field '3h'
$rain = isset($data->rain) ? (array) $data->rain : [];
$rainUnit = !empty($rain) ? key($rain) : '';
$rainValue = !empty($rain) ? current($rain) : 0.0;
$this->precipitation = new Unit($rainValue, $rainUnit);

$this->sun = new Sun(\DateTime::createFromFormat('U', $data->sys->sunrise, $utctz), \DateTime::createFromFormat('U', $data->sys->sunset, $utctz));
$this->weather = new WeatherObj($data->weather[0]->id, $data->weather[0]->description, $data->weather[0]->icon);
$this->lastUpdate = \DateTime::createFromFormat('U', $data->dt, $utctz);
}
}
}
95 changes: 95 additions & 0 deletions Cmfcmf/OpenWeatherMap/CurrentWeatherGroup.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
<?php
/**
* OpenWeatherMap-PHP-API — A php api to parse weather data from http://www.OpenWeatherMap.org .
*
* @license MIT
*
* Please see the LICENSE file distributed with this source code for further
* information regarding copyright and licensing.
*
* Please visit the following links to read about the usage policies and the license of
* OpenWeatherMap before using this class:
*
* @see http://www.OpenWeatherMap.org
* @see http://www.OpenWeatherMap.org/terms
* @see http://openweathermap.org/appid
*/

namespace Cmfcmf\OpenWeatherMap;

use Cmfcmf\OpenWeatherMap;

/**
* Class CurrentWeatherGroup used to hold the current weather data for a group of cities.
*/
class CurrentWeatherGroup implements \Iterator
{
/**
* An array of {@link CurrentWeather} objects.
*
* @var CurrentWeather[]
*
* @see CurrentWeather The CurrentWeather class.
*/
private $currentWeathers;

/**
* @internal
*/
private $position = 0;

/**
* Create a new current weathers group object.
*
* @param \stdClass $json The current weathers group json.
* @param string $units The units used.
*
* @internal
*/
public function __construct(\stdClass $json, $units)
{
foreach ($json->list as $currentWeather) {
$this->currentWeathers[] = new CurrentWeather($currentWeather, $units);
}
}

/**
* @internal
*/
public function rewind()
{
$this->position = 0;
}

/**
* @internal
*/
public function current()
{
return $this->currentWeathers[$this->position];
}

/**
* @internal
*/
public function key()
{
return $this->current()->city->id;
}

/**
* @internal
*/
public function next()
{
++$this->position;
}

/**
* @internal
*/
public function valid()
{
return isset($this->currentWeathers[$this->position]);
}
}

0 comments on commit 654211b

Please sign in to comment.