* @category Horde
* @package Service_Weather
*/
abstract class Horde_Service_Weather_Forecast_Base implements IteratorAggregate
{
/**
* The forecast properties as returned from the forecast request.
*
* @var array
*/
protected $_properties = array();
/**
* Local cache of forecast periods
*
* @var array
*/
protected $_periods = array();
/**
* Forecast type
*
* @var integer A Horde_Service_Weather::FORECAST_TYPE_* constant.
*/
protected $_type;
/**
* Maximum forecast length to return. Defaults to sufficiently high number
* to ensure all available days returned by default.
*/
protected $_maxDays = 20;
/**
* Parent Weather driver.
*
* @var Horde_Service_Weather_Base
*/
public $weather;
/**
* Array of supported "detailed" forecast fields. To be populated by
* concrete classes.
*
* @var array
*/
public $fields = array();
/**
* Advertise how detailed the forecast period is.
*
* FORECAST_TYPE_STANDARD - Each Period represents a full day
* FORECAST_TYPE_DETAILED - Each period represents either day or night.
* FORECAST_TYPE_HOURLY - Each period represents a single hour.
*
*
* @var integer
*/
public $detail = Horde_Service_Weather::FORECAST_TYPE_STANDARD;
/**
* Const'r
*
* @param array $properties Forecast properties.
* @param Horde_Service_Weather_base $weather The base driver.
* @param integer $type The forecast type.
*/
public function __construct(
$properties,
Horde_Service_Weather_Base $weather,
$type = Horde_Service_Weather::FORECAST_TYPE_STANDARD)
{
$this->_properties = $properties;
$this->weather = $weather;
$this->_type = $type;
}
/**
* Return the forecast for the specified ordinal day.
*
* @param integer $day The forecast day to return.
*
* @return Horde_Service_Weather_Period_Base
*/
public function getForecastDay($day)
{
return $this->_periods[$day];
}
/**
* Limit the returned number of forecast days. Used for emulating a smaller
* forecast length than the provider supports or for using one, longer
* request to supply two different forecast length requests.
*
* @param integer $days The number of days to return.
*/
public function limitLength($days)
{
$this->_maxDays = $days;
}
/**
* Return the time of the forecast, in local (to station) time.
*
* @return Horde_Date The time of the forecast.
*/
abstract public function getForecastTime();
/**
* Return an ArrayIterator
*
* @return ArrayIterator
*/
public function getIterator()
{
return new ArrayIterator(array_slice($this->_periods, 0, $this->_maxDays));
}
} Horde_Service_Weather-2.3.2/lib/Horde/Service/Weather/Forecast/Owm.php 0000664 0001750 0001750 00000003673 12654070567 023676 0 ustar jan jan
* @license http://www.horde.org/licenses/bsd BSD
* @category Horde
* @package Service_Weather
*/
/**
* Horde_Service_Weather_Forecast_Wwo
*
* @author Michael J Rubinsky
* @category Horde
* @package Service_Weather
*/
class Horde_Service_Weather_Forecast_Owm extends Horde_Service_Weather_Forecast_Base
{
/**
* @see Horde_Service_Weather_Forecast_Base::$fields
*/
public $fields = array(Horde_Service_Weather::FORECAST_FIELD_WIND);
/**
* Const'r
*
* @see Horde_Service_Weather_Forecast_Base::__construct()
*/
public function __construct(
$properties,
Horde_Service_Weather_Base $weather,
$type = Horde_Service_Weather::FORECAST_TYPE_STANDARD)
{
parent::__construct($properties, $weather, $type);
$this->_parseStd();
}
/**
* Return the forecast time. Note that Wwo doesn't provide the validity time
* for the forecast, so we use the last known station time. File this under
* the "good enough" file.
*
* @see Horde_Service_Weather_Forecast_Base::getForecastTime()
*/
public function getForecastTime()
{
return new Horde_Date($this->weather->getStation()->time);
}
/**
* Parse a stdRequest
*
* @throws Horde_Service_Weather_Exception
*/
protected function _parseStd()
{
if (empty($this->_properties)) {
throw new Horde_Service_Weather_Exception('No forecast data to parse.');
}
foreach ($this->_properties as $period => $values) {
$period = new Horde_Service_Weather_Period_Owm($values, $this);
$this->_periods[] = $period;
}
}
} Horde_Service_Weather-2.3.2/lib/Horde/Service/Weather/Forecast/WeatherUnderground.php 0000664 0001750 0001750 00000004544 12654070567 026746 0 ustar jan jan
* @license http://www.horde.org/licenses/bsd BSD
* @category Horde
* @package Service_Weather
*/
/**
* Horde_Service_Weather_Forecast_WeatherUnderground
*
* @author Michael J Rubinsky
* @category Horde
* @package Service_Weather
*/
class Horde_Service_Weather_Forecast_WeatherUnderground extends Horde_Service_Weather_Forecast_Base
{
/**
* @see Horde_Service_Weather_Forecast_Base::$fields
*/
public $fields = array(
Horde_Service_Weather::FORECAST_FIELD_WIND,
Horde_Service_Weather::FORECAST_FIELD_HUMIDITY,
Horde_Service_Weather::FORECAST_FIELD_PRECIPITATION);
/**
* Const'r
*
* @see Horde_Service_Weather_Forecast_Base::__construct()
*/
public function __construct(
$properties,
Horde_Service_Weather_Base $weather,
$type = Horde_Service_Weather::FORECAST_TYPE_STANDARD)
{
parent::__construct($properties, $weather, $type);
switch ($type) {
case Horde_Service_Weather::FORECAST_TYPE_STANDARD:
$this->_parseStd();
break;
case Horde_Service_Weather::FORECAST_TYPE_HOURLY:
$this->_parseHourly();
}
}
/**
* Return the forecast time.
*
* @see Horde_Service_Weather_Forecast_Base::getForecastTime()
*/
public function getForecastTime()
{
return new Horde_Date($this->_properties['txt_forecast']->date);
}
/**
* Parse the Std forecast data
*
* @throws Horde_Service_Weather_Exception
*/
protected function _parseStd()
{
if (empty($this->_properties)) {
throw new Horde_Service_Weather_Exception('No forecast data to parse.');
}
foreach ($this->_properties['simpleforecast']->forecastday as $period => $values) {
$this->_periods[] = new Horde_Service_Weather_Period_WeatherUnderground((array)$values, $this);
}
}
// @TODO: Use the hourly forecast to maybe get a "day"/"night"
protected function _parseHourly()
{
throw Horde_Exception('Not currently implemented.');
}
} Horde_Service_Weather-2.3.2/lib/Horde/Service/Weather/Forecast/Wwo.php 0000664 0001750 0001750 00000003672 12654070567 023707 0 ustar jan jan
* @license http://www.horde.org/licenses/bsd BSD
* @category Horde
* @package Service_Weather
*/
/**
* Horde_Service_Weather_Forecast_Wwo
*
* @author Michael J Rubinsky
* @category Horde
* @package Service_Weather
*/
class Horde_Service_Weather_Forecast_Wwo extends Horde_Service_Weather_Forecast_Base
{
/**
* @see Horde_Service_Weather_Forecast_Base::$fields
*/
public $fields = array(Horde_Service_Weather::FORECAST_FIELD_WIND);
/**
* Const'r
*
* @see Horde_Service_Weather_Forecast_Base::__construct()
*/
public function __construct(
$properties,
Horde_Service_Weather_Base $weather,
$type = Horde_Service_Weather::FORECAST_TYPE_STANDARD)
{
parent::__construct($properties, $weather, $type);
$this->_parseStd();
}
/**
* Return the forecast time. Note that Wwo doesn't provide the validity time
* for the forecast, so we use the last known station time. File this under
* the "good enough" file.
*
* @see Horde_Service_Weather_Forecast_Base::getForecastTime()
*/
public function getForecastTime()
{
return new Horde_Date($this->weather->getStation()->time);
}
/**
* Parse a stdRequest
*
* @throws Horde_Service_Weather_Exception
*/
protected function _parseStd()
{
if (empty($this->_properties)) {
throw new Horde_Service_Weather_Exception('No forecast data to parse.');
}
foreach ($this->_properties as $period => $values) {
$period = new Horde_Service_Weather_Period_Wwo($values, $this);
$this->_periods[] = $period;
}
}
} Horde_Service_Weather-2.3.2/lib/Horde/Service/Weather/Forecast/Wwov2.php 0000664 0001750 0001750 00000003266 12654070567 024156 0 ustar jan jan
* @license http://www.horde.org/licenses/bsd BSD
* @category Horde
* @package Service_Weather
*/
/**
* Horde_Service_Weather_Forecast_Wwo
*
* @author Michael J Rubinsky
* @category Horde
* @package Service_Weather
*/
class Horde_Service_Weather_Forecast_Wwov2 extends Horde_Service_Weather_Forecast_Wwo
{
/**
* @see Horde_Service_Weather_Forecast_Base::$fields
*/
public $fields = array(
Horde_Service_Weather::FORECAST_FIELD_WIND,
Horde_Service_Weather::FORECAST_FIELD_HUMIDITY,
Horde_Service_Weather::FORECAST_FIELD_PRECIPITATION);
/**
* Parse a stdRequest
*
* @throws Horde_Service_Weather_Exception
*/
protected function _parseStd()
{
if (empty($this->_properties)) {
throw new Horde_Service_Weather_Exception('No forecast data to parse.');
}
// @todo Need to refactor this when we support hourly data.
foreach ($this->_properties as $period => $values) {
$data = new stdClass();
foreach ($values as $k => $v) {
if ($k != 'hourly') {
$data->{$k} = $v;
}
}
foreach ($values->hourly[0] as $k => $v) {
$data->{$k} = $v;
}
$period = new Horde_Service_Weather_Period_Wwov2($data, $this);
$this->_periods[] = $period;
}
}
} Horde_Service_Weather-2.3.2/lib/Horde/Service/Weather/Period/Base.php 0000664 0001750 0001750 00000005674 12654070567 023465 0 ustar jan jan
* @license http://www.horde.org/licenses/bsd BSD
* @category Horde
* @package Service_Weather
*/
/**
* Horde_Service_Weather_Period_Base class
*
* @property is_pm Indicates if this is for an evening period.
* @property hour Indicates if this is for an hourly period.
* @property precipitation_percent Change of precipitation percent.
* @property period The cardinal number of this period.
* @property humidity Humidity percent.
* @property wind_speed Wind speed, in currently configured units.
* @property wind_direction Cardinal wind direction e.g., NNW.
* @property wind_degrees Wind direction, in degrees.
* @property wind_gust Wind gust speed, in currently configured units.
* @property snow_total Daily snow totals, in configured units.
* @property rain_total Daily rain totals, in configured units.
* @property conditions Forecast conditions e.g., "Sunny".
* @property icon_url Url to a condition icon.
* @property icon Name of condition icon.
* @property date Date for this period.
* @property high Forecast high temp, in configured units.
* @property low Forecast low temp, in configured units.
*
* @author Michael J Rubinsky
* @category Horde
* @package Service_Weather
*/
class Horde_Service_Weather_Period_Base
{
/**
* Properties for this single peridd, as returned from the forecast request.
*
* @var mixed
*/
protected $_properties;
/**
* Reference to parent forecast object.
*
* @var Horde_Service_Weather_Forecast_Base
*/
protected $_forecast;
/**
* Const'r
*
* @param mixed $properties Current properties.
* @param Horde_Service_Forecast_Base $forecast The parent forecast.
*
* @return Horde_Service_Weather_Current
*/
public function __construct($properties, Horde_Service_Weather_Forecast_Base $forecast)
{
$this->_forecast = $forecast;
$this->_properties = $properties;
}
/**
* Default implementation - just return the value set.
*
* @param string $property The requested property.
*
* @return mixed The property value.
* @throws Horde_Service_Weather_Exception_InvalidProperty
*/
public function __get($property)
{
if (isset($this->_properties[$property])) {
return $this->_properties[$property];
}
throw new Horde_Service_Weather_Exception_InvalidProperty('This provider does not support that property');
}
} Horde_Service_Weather-2.3.2/lib/Horde/Service/Weather/Period/Owm.php 0000664 0001750 0001750 00000004671 12654070567 023351 0 ustar jan jan
* @license http://www.horde.org/licenses/bsd BSD
* @category Horde
* @package Service_Weather
*/
/**
* Horde_Service_Weather_Period_Wwo
*
* @author Michael J Rubinsky
* @category Horde
* @package Service_Weather
*/
class Horde_Service_Weather_Period_Owm extends Horde_Service_Weather_Period_Base
{
/**
* Property Map
*
* @TODO Figure out what to do with the 'skyicon' value - which is sometimes
* different than the icon and icon_url. Also, should add a icon set
* property to allow using other icon sets e.g., {icon_set_url}/{icon}.gif
*
* @var array
*/
protected $_map = array();
/**
* Accessor so we can lazy-parse the results.
*
* @param string $property The property name.
*
* @return mixed The value of requested property
* @throws Horde_Service_Weather_Exception_InvalidProperty
*/
public function __get($property)
{
switch ($property) {
case 'humidity':
case 'precipitation_percent':
case 'wind_gust':
case 'snow_total':
case 'rain_total':
return false;
case 'conditions':
return Horde_Service_Weather_Translation::t($this->_properties->weather[0]->main);
case 'is_pm':
return false;
case 'hour':
return false;
case 'date':
return new Horde_Date($this->_properties->date);
case 'high':
return round($this->_properties->temp->day);
case 'low':
return round($this->_properties->temp->night);
case 'icon':
return $this->_forecast->weather->iconMap[
str_replace('.png', '', $this->_properties->weather[0]->icon)
];
case 'wind_direction':
return Horde_Service_Weather::degToDirection($this->_properties->deg);
case 'wind_degrees':
return $this->_properties->deg;
case 'wind_speed':
return $this->_properties->speed;
default:
throw new Horde_Service_Weather_Exception_InvalidProperty('This provider does not support the "' . $property . '" property');
}
}
} Horde_Service_Weather-2.3.2/lib/Horde/Service/Weather/Period/WeatherUnderground.php 0000664 0001750 0001750 00000011601 12654070567 026412 0 ustar jan jan
* @license http://www.horde.org/licenses/bsd BSD
* @category Horde
* @package Service_Weather
*/
/**
* Horde_Service_Weather_Period_WeatherUnderground
*
* @author Michael J Rubinsky
* @category Horde
* @package Service_Weather
*/
class Horde_Service_Weather_Period_WeatherUnderground extends Horde_Service_Weather_Period_Base
{
/**
* Property Map
*
* @TODO Figure out what to do with the 'skyicon' value - which is sometimes
* different than the icon and icon_url. Also, should add a icon set
* property to allow using other icon sets e.g., {icon_set_url}/{icon}.gif
*
* @var array
*/
protected $_map = array(
'conditions' => 'conditions',
'icon_url' => 'icon_url',
'precipitation_percent' => 'pop',
'period' => 'period',
'humidity' => 'avehumidity',
);
/**
* Accessor so we can lazy-parse the results.
*
* @param string $property The property name.
*
* @return mixed The value of requested property
* @throws Horde_Service_Weather_Exception_InvalidProperty
*/
public function __get($property)
{
switch ($property) {
case 'is_pm':
// Wunderground only supports standard
return false;
case 'hour':
// Wunderground supports this, but we don't.
return false;
case 'date':
$date = new Horde_Date(array(
'year' => $this->_properties['date']->year,
'month' => $this->_properties['date']->month,
'mday' => $this->_properties['date']->day));
$date->hour = $this->_properties['date']->hour;
$date->min = $this->_properties['date']->min;
$date->setTimezone($this->_properties['date']->tz_long);
return $date;
case 'high':
if ($this->_forecast->weather->units == Horde_Service_Weather::UNITS_STANDARD) {
return $this->_properties['high']->fahrenheit !== '' ?
$this->_properties['high']->fahrenheit :
Horde_Service_Weather_Translation::t("N/A");
}
return $this->_properties['high']->celsius;
case 'low':
if ($this->_forecast->weather->units == Horde_Service_Weather::UNITS_STANDARD) {
return $this->_properties['low']->fahrenheit !== '' ?
$this->_properties['low']->fahrenheit :
Horde_Service_Weather_Translation::t("N/A");
}
return $this->_properties['low']->celsius;
case 'icon':
return $this->_forecast->weather->iconMap[$this->_properties['icon']];
case 'wind_direction':
return strlen($this->_properties['avewind']->dir)
? Horde_Service_Weather_Translation::t($this->_properties['avewind']->dir)
: Horde_Service_Weather_Translation::t("N/A");
case 'wind_degrees':
return strlen($this->_properties['avewind']->dir)
? $this->_properties['avewind']->degrees
: Horde_Service_Weather_Translation::t("N/A");
case 'wind_speed':
if (strlen($this->_properties['avewind']->dir)) {
if ($this->_forecast->weather->units == Horde_Service_Weather::UNITS_STANDARD) {
return $this->_properties['avewind']->mph;
}
return $this->_properties['avewind']->kph;
} else {
return Horde_Service_Weather_Translation::t("N/A");
}
case 'wind_gust':
if ($this->_forecast->weather->units == Horde_Service_Weather::UNITS_STANDARD) {
return $this->_properties['maxwind']->mph;
}
return $this->_properties['maxwind']->kph;
case 'rain_total':
if ($this->_forecast->weather->units == Horde_Service_Weather::UNITS_STANDARD) {
return $this->_properties['qpf_allday']->in;
}
return $this->_properties['qpf_allday']->mm;
case 'snow_total':
if ($this->_forecast->weather->units == Horde_Service_Weather::UNITS_STANDARD) {
return $this->_properties['snow_allday']->in;
}
return $this->_properties['snow_allday']->cm;
default:
if (!empty($this->_map[$property])) {
return Horde_Service_Weather_Translation::t($this->_properties[$this->_map[$property]]);
}
throw new Horde_Service_Weather_Exception_InvalidProperty('This provider does not support the "' . $property . '" property');
}
}
} Horde_Service_Weather-2.3.2/lib/Horde/Service/Weather/Period/Wwo.php 0000664 0001750 0001750 00000005762 12654070567 023365 0 ustar jan jan
* @license http://www.horde.org/licenses/bsd BSD
* @category Horde
* @package Service_Weather
*/
/**
* Horde_Service_Weather_Period_Wwo
*
* @author Michael J Rubinsky
* @category Horde
* @package Service_Weather
*/
class Horde_Service_Weather_Period_Wwo extends Horde_Service_Weather_Period_Base
{
/**
* Property Map
*
* @TODO Figure out what to do with the 'skyicon' value - which is sometimes
* different than the icon and icon_url. Also, should add a icon set
* property to allow using other icon sets e.g., {icon_set_url}/{icon}.gif
*
* @var array
*/
protected $_map = array();
/**
* Accessor so we can lazy-parse the results.
*
* @param string $property The property name.
*
* @return mixed The value of requested property
* @throws Horde_Service_Weather_Exception_InvalidProperty
*/
public function __get($property)
{
switch ($property) {
case 'humidity':
case 'precipitation_percent':
case 'wind_gust':
case 'snow_total':
case 'rain_total':
return false;
case 'conditions':
return Horde_Service_Weather_Translation::t($this->_properties->weatherDesc[0]->value);
case 'icon_url':
return $this->_properties->weatherIconUrl[0]->value;
case 'is_pm':
return false;
case 'hour':
return false;
case 'date':
return new Horde_Date($this->_properties->date);
case 'high':
if ($this->_forecast->weather->units == Horde_Service_Weather::UNITS_STANDARD) {
return $this->_properties->tempMaxF ;
}
return $this->_properties->tempMaxC;
case 'low':
if ($this->_forecast->weather->units == Horde_Service_Weather::UNITS_STANDARD) {
return $this->_properties->tempMinF;
}
return $this->_properties->tempMinC;
case 'icon':
return $this->_forecast->weather->iconMap[
str_replace('.png', '', basename($this->_properties->weatherIconUrl[0]->value))
];
case 'wind_direction':
return $this->_properties->winddirection;
case 'wind_degrees':
return $this->_properties->winddirDegree;
case 'wind_speed':
if ($this->_forecast->weather->units == Horde_Service_Weather::UNITS_STANDARD) {
return $this->_properties->windspeedMiles;
}
return $this->_properties->windspeedKmph;
default:
throw new Horde_Service_Weather_Exception_InvalidProperty('This provider does not support the "' . $property . '" property');
}
}
} Horde_Service_Weather-2.3.2/lib/Horde/Service/Weather/Period/Wwov2.php 0000664 0001750 0001750 00000007506 12654070567 023633 0 ustar jan jan
* @license http://www.horde.org/licenses/bsd BSD
* @category Horde
* @package Service_Weather
*/
/**
* Horde_Service_Weather_Period_Wwo
*
* @author Michael J Rubinsky
* @category Horde
* @package Service_Weather
*/
class Horde_Service_Weather_Period_Wwov2 extends Horde_Service_Weather_Period_Base
{
/**
* Property Map
*
* @TODO Figure out what to do with the 'skyicon' value - which is sometimes
* different than the icon and icon_url. Also, should add a icon set
* property to allow using other icon sets e.g., {icon_set_url}/{icon}.gif
*
* @var array
*/
protected $_map = array();
/**
* Accessor so we can lazy-parse the results.
*
* @param string $property The property name.
*
* @return mixed The value of requested property
* @throws Horde_Service_Weather_Exception_InvalidProperty
*/
public function __get($property)
{
switch ($property) {
case 'humidity':
return $this->_properties->humidity;
case 'precipitation_percent':
// There is no "precipitation" field, so if we don't have
// rain, check for snow, and return 0 if we have neither.
return !empty($this->_properties->chanceofrain)
? $this->_properties->chanceofrain
: (!empty($this->_properties->chanceofsnow)
? $this->_properties->chanceofsnow
: 0);
case 'wind_gust':
if ($this->_forecast->weather->units == Horde_Service_Weather::UNITS_STANDARD) {
return $this->_properties->WindGustMiles;
}
return $this->_properties->WindGustKmph;
case 'snow_total':
case 'rain_total':
if ($this->_forecast->weather->units == Horde_Service_Weather::UNITS_STANDARD) {
return $this->_properties->precipInches;
}
return $this->_properties->precipMM;
case 'conditions':
return Horde_Service_Weather_Translation::t($this->_properties->weatherDesc[0]->value);
case 'icon_url':
return $this->_properties->weatherIconUrl[0]->value;
case 'is_pm':
return false;
case 'hour':
return false;
case 'date':
return new Horde_Date($this->_properties->date);
case 'high':
if ($this->_forecast->weather->units == Horde_Service_Weather::UNITS_STANDARD) {
return $this->_properties->maxtempF ;
}
return $this->_properties->maxtempC;
case 'low':
if ($this->_forecast->weather->units == Horde_Service_Weather::UNITS_STANDARD) {
return $this->_properties->mintempF;
}
return $this->_properties->mintempC;
case 'icon':
return $this->_forecast->weather->iconMap[
str_replace('.png', '', basename($this->_properties->weatherIconUrl[0]->value))
];
case 'wind_direction':
return $this->_properties->winddir16Point;
case 'wind_degrees':
return $this->_properties->winddirDegree;
case 'wind_speed':
if ($this->_forecast->weather->units == Horde_Service_Weather::UNITS_STANDARD) {
return $this->_properties->windspeedMiles;
}
return $this->_properties->windspeedKmph;
default:
throw new Horde_Service_Weather_Exception_InvalidProperty('This provider does not support the "' . $property . '" property');
}
}
} Horde_Service_Weather-2.3.2/lib/Horde/Service/Weather/Base.php 0000664 0001750 0001750 00000021431 12654070567 022230 0 ustar jan jan
* @license http://www.horde.org/licenses/bsd BSD
* @category Horde
* @package Service_Weather
*/
/**
* Horde_Service_Weather_Base class
*
* @author Michael J Rubinsky
* @category Horde
* @package Service_Weather
*/
abstract class Horde_Service_Weather_Base
{
/**
* Parameters
*
* @var array
*/
protected $_params;
/**
* Cache object
*
* @var Horde_Cache
*/
protected $_cache;
/**
* Lifetime for cached data.
*
* @var integer
*/
protected $_cache_lifetime = 21600;
/**
* Units to display results in.
*
* @var integer
*/
public $units = Horde_Service_Weather::UNITS_STANDARD;
/**
* URL to a logo for this provider
*
* @var string
*/
public $logo;
/**
* URL to the provider's site
*
* @var string
*/
public $link;
/**
* Title for the provider
*
* @var string
*/
public $title;
/**
* Driver spcific icon map for condition icons. Made public so icons can
* be overridden in client code if desired.
*
* @var array
*/
public $iconMap = array();
/**
* The http client
*
* @var Horde_Http_Client
*/
protected $_http;
/**
* Local cache of current conditions
*
*/
protected $_current;
/**
* Local cache of forecast
*
* @var Horde_Service_Weather_Forecast_Base
*/
protected $_forecast;
/**
* Local cache of station data
*
* @var Horde_Service_Weather_Station
*/
protected $_station;
/**
* Last location requested.
*
* @var string
*/
protected $_lastLocation;
/**
* Last requested forecast length.
*
* @var integer
*/
protected $_lastLength;
protected $_alerts = array();
protected $_radar;
/**
* Constructor.
*
* @param array $params Parameters:
* - cache: (Horde_Cache) Optional Horde_Cache object.
* - cache_lifetime: (integer) Lifetime of cached data, if caching.
* - http_client: (Horde_Http_Client) Required http client object.
*/
public function __construct(array $params = array())
{
if (empty($params['http_client'])) {
throw new InvalidArgumentException('Missing http_client parameter.');
}
$this->_http = $params['http_client'];
unset($params['http_client']);
if (!empty($params['cache'])) {
$this->_cache = $params['cache'];
unset($params['cache']);
if (!empty($params['cache_lifetime'])) {
$this->_cache_lifetime = $params['cache_lifetime'];
unset($params['cache_lifetime']);
}
}
$this->_params = $params;
}
/**
* Returns the current observations.
*
* @param string $location The location string.
*
* @return Horde_Service_Weather_Current_Base
*/
abstract public function getCurrentConditions($location);
/**
* Returns the forecast for the current location.
*
* @param string $location The location code.
* @param integer $length The forecast length, a
* Horde_Service_Weather::FORECAST_* constant.
* @param integer $type The type of forecast to return, a
* Horde_Service_Weather::FORECAST_TYPE_* constant
*
* @return Horde_Service_Weather_Forecast_Base
*/
abstract public function getForecast(
$location,
$length = Horde_Service_Weather::FORECAST_3DAY,
$type = Horde_Service_Weather::FORECAST_TYPE_STANDARD);
/**
* Searches locations.
*
* @param string $location The location string to search.
* @param integer $type The type of search to perform, a
* Horde_Service_Weather::SEARCHTYPE_* constant.
*
* @return Horde_Service_Weather_Station The search location suitable to use
* directly in a weather request.
* @throws Horde_Service_Weather_Exception
*/
abstract public function searchLocations(
$location,
$type = Horde_Service_Weather::SEARCHTYPE_STANDARD);
/**
* Get array of supported forecast lengths.
*
* @return array The array of supported lengths.
*/
abstract public function getSupportedForecastLengths();
/**
* Return array of weather alerts, if available.
*
* @return array
*/
public function getAlerts($location)
{
return $this->_alerts;
}
/**
* Return the URL to a (possibly animated) radar image.
*
* @param string $location The location
*
* @return string|boolean The Url, or false if not available.
*/
public function getRadarImageUrl($location)
{
return false;
}
/**
* Return the URL a OpenLayers suitable tile server.
*
* @param string $location The location.
* @param string $type The optional layer type.
*
* @return string|boolean The Url, or false if not available.
*/
public function getTileServerUrl($location, $type = null)
{
return false;
}
/**
* Searches for locations that begin with the text in $search.
*
* @param string $search The text to search.
*
* @return array An array of stdClass objects with 'name' and 'code'
* properties.
* @throws Horde_Service_Weather_Exception
*/
public function autocompleteLocation($search)
{
throw new Horde_Service_Weather_Exception('Not implemented');
}
/**
* Returns a mapping of units for each UNIT type.
*
* @param integer $type The units for measurement. A
* Horde_Service_Weather::UNITS_* constant.
*
* @return array The mapping of measurements (as keys) and units (as values).
*/
public function getUnits($type = null)
{
if (empty($type)) {
$type = $this->units;
}
if ($type == Horde_Service_Weather::UNITS_STANDARD) {
return array(
'temp' => Horde_Service_Weather_Translation::t('F'),
'wind' => Horde_Service_Weather_Translation::t('mph'),
'pres' => Horde_Service_Weather_Translation::t('inches'),
'vis' => Horde_Service_Weather_Translation::t('miles'),
'rain' => Horde_Service_Weather_Translation::t('inches'),
'snow' => Horde_Service_Weather_Translation::t('inches'),
);
}
return array(
'temp' => Horde_Service_Weather_Translation::t('C'),
'wind' => Horde_Service_Weather_Translation::t('kph'),
'pres' => Horde_Service_Weather_Translation::t('millibars'),
'vis' => Horde_Service_Weather_Translation::t('km'),
'rain' => Horde_Service_Weather_Translation::t('millimeters'),
'snow' => Horde_Service_Weather_Translation::t('centimeters'),
);
}
/**
* Returns the station information associated with the last request.
*
* @return Horde_Service_Weather_Station
* @throws Horde_Service_Weather_Exception if not request has yet been made.
*/
public function getStation()
{
if (empty($this->_station)) {
throw new Horde_Service_Weather_Exception('No request made.');
}
return $this->_station;
}
/**
* Check if an IP address is a globally unique address and not in RFC1918 or
* RFC3330 address space.
*
* @param string $ip The IPv4 IP address to check.
*
* @return boolean True if the IP address is globally unique, otherwise
* false.
* @link http://tools.ietf.org/html/rfc3330
* @link http://www.faqs.org/rfcs/rfc1918.html
*/
protected function _ipIsUnique($ip)
{
// Make sure it's sane
$parts = explode('.', $ip);
if (count($parts) != 4) {
return false;
}
// zero config IPs RFC3330
if ($parts[0] == 169 && $parts[1] == 254) {
return false;
}
// reserved RFC 1918
if ($parts[0] == 10 ||
($parts[0] == 192 && $parts[1] == 168) ||
($parts[0] == 172 && ($parts[1] >= 16 && $parts[1] <= 31))) {
return false;
}
// Loopback
if ($parts[0] == 127) {
return false;
}
return true;
}
}
Horde_Service_Weather-2.3.2/lib/Horde/Service/Weather/Exception.php 0000664 0001750 0001750 00000000553 12654070567 023316 0 ustar jan jan
* @category Horde
* @license http://www.horde.org/licenses/bsd BSD
* @package Service_Weather
*/
class Horde_Service_Weather_Exception extends Horde_Exception_Wrapped
{
}
Horde_Service_Weather-2.3.2/lib/Horde/Service/Weather/Owm.php 0000664 0001750 0001750 00000026366 12654070567 022134 0 ustar jan jan
* @license http://www.horde.org/licenses/bsd BSD
* @category Horde
* @package Service_Weather
*/
/**
* Horde_Service_Weather_Owm
*
* @author Michael J Rubinsky
* @category Horde
* @package Service_Weather
*/
class Horde_Service_Weather_Owm extends Horde_Service_Weather_Base
{
const API_URL = 'http://api.openweathermap.org/data/2.5';
/**
* @see Horde_Service_Weather_Base::$title
* @var string
*/
public $title = 'OpenWeatherMap';
/**
* @see Horde_Service_Weather_Base::$link
* @var string
*/
public $link = 'http://openweathermap.org';
/**
* @see Horde_Service_Weather::$iconMap
*/
public $iconMap = array(
'01d' => '32.png',
'01n' => '33.png',
'02d' => '30.png', //Few Clouds,day
'02n' => '29.png', //Few Clouds,pm
'03d' => '28.png', //Broken clouds
'03n' => '27.png',
'04d' => '26.png', //Overcast
'04d' => '26.png',
'09d' => '11.png',
'09n' => '40.png',
'10d' => '12.png',
'10n' => '30.png',
'11d' => '0.png',
'11n' => '47.png',
'13d' => '16.png',
'13n' => '42.png',
);
/**
* Owm API key.
*
* @var string
*/
protected $_key;
protected $_locationCode;
/**
* Constructor.
*
* @param array $params Parameters:
* - cache: (Horde_Cache) Optional Horde_Cache object.
* - cache_lifetime: (integer) Lifetime of cached data, if caching.
* - http_client: (Horde_Http_Client) Required http client object.
* - apikey: (string) Require api key for Wwo.
* - apiVersion: (integer) Version of the API to use.
* Defaults to v1 for BC reasons.
*
* @return Horde_Service_Weather_Wwo
*/
public function __construct(array $params = array())
{
// Check required api key parameters here...
if (empty($params['apikey'])) {
throw new InvalidArgumentException('Missing required API Key parameter.');
}
$this->_key = $params['apikey'];
unset($params['apikey']);
parent::__construct($params);
}
/**
* Obtain the current observations.
*
* @see Horde_Service_Weather_Base::getCurrentConditions
*
* @return Horde_Service_Weather_Current_Wwo
*/
public function getCurrentConditions($location)
{
$this->_getCommonElements($location);
return $this->_current;
}
/**
* Obtain the forecast for the current location.
*
* @see Horde_Service_Weather_Base::getForecast
*/
public function getForecast(
$location,
$length = Horde_Service_Weather::FORECAST_3DAY,
$type = Horde_Service_Weather::FORECAST_TYPE_STANDARD)
{
$this->_getCommonElements($location);
return $this->_forecast;
}
/**
* Search for a valid location code.
*
* @see Horde_Service_Weather_Base::searchLocations
*/
public function searchLocations($location, $type = Horde_Service_Weather::SEARCHTYPE_STANDARD)
{
return current($this->_parseSearchLocations($this->_searchLocations($location)));
}
/**
* Return an autocomplete request result.
* @todo Provide switch to use another autocomplete API since
* Owm does not provide one. E.g., Wunderground provides free,
* key-less access to their autocomplete API.
*
* @see Horde_Service_Weather_Base::autocompleteLocation
*/
public function autocompleteLocation($search)
{
$results = $this->searchLocations($search);
return $this->_parseAutocomplete($results);
}
/**
* Return the supported forecast lengths.
*
* @see Horde_Service_Weather_Base::getSupportedForecastLengths
*/
public function getSupportedForecastLengths()
{
return array(
3 => Horde_Service_Weather::FORECAST_3DAY,
5 => Horde_Service_Weather::FORECAST_5DAY,
7 => Horde_Service_Weather::FORECAST_7DAY,
10 => Horde_Service_Weather::FORECAST_10DAY
);
}
/**
* Populates some common data used by forecasts and current conditions.
*
* @param string $location The location identifier.
* @param integer $length The forecast length.
*/
protected function _getCommonElements($location, $length = Horde_Service_Weather::FORECAST_5DAY)
{
if (!empty($this->_current) && $location == $this->_lastLocation
&& $this->_lastLength == $length) {
return;
}
$this->_lastLength = $length;
$this->_lastLocation = $location;
$weather_url = new Horde_Url(self::API_URL . '/weather');
$forecast_url = new Horde_Url(self::API_URL . '/forecast/daily');
if (is_int($location)) {
$weather_url->add(array(
'id' => $location
));
$forecast_url->add(array(
'id' => $location
));
} else {
$weather_url->add(array(
'q' => $location
));
$forecast_url->add(array(
'q' => $location
));
}
$current_results = $this->_makeRequest($weather_url);
$forecast_results = $this->_makeRequest($forecast_url);
$this->_current = $this->_parseCurrent($current_results);
// Use the minimum station data provided by forecast request to
// fetch the full station data.
// @todo - use the weather station api?
$station = $this->_parseStation($current_results);
// // Sunrise/Sunset
$station->sunrise = new Horde_Date($current_results->sys->sunrise, 'UTC');
$station->sunset = new Horde_Date($current_results->sys->sunset, 'UTC');
$station->time = $this->_current->time;
$this->_station = $station;
$this->_forecast = $this->_parseForecast($forecast_results->list);
}
/**
* Parses the JSON response for a location request into a station object.
*
* @param StdClass $station The response from a Location request.
*
* @return Horde_Service_Weather_Station
*/
protected function _parseStation($station)
{
$properties = array(
'name' => $station->name,
'city' => $station->name,
'state' => '',
'country' => $station->sys->country,
'country_name' => '',
'lat' => $station->coord->lat,
'lon' => $station->coord->lon,
'zip' => '',
'code' => $station->id
);
return new Horde_Service_Weather_Station($properties);
}
/**
* Parses the forecast data.
*
* @param stdClass $forecast The result of the forecast request.
*
* @return Horde_Service_Weather_Forecast_Wwo The forecast.
*/
protected function _parseForecast($forecast)
{
$forecast = new Horde_Service_Weather_Forecast_Owm($forecast, $this);
return $forecast;
}
/**
* Parse the current_conditions response.
*
* @param stdClass $current The current_condition request response object
*
* @return Horde_Service_Weather_Current
*/
protected function _parseCurrent($current)
{
// The Current object takes care of the parsing/mapping.
$current = new Horde_Service_Weather_Current_Owm($current, $this);
return $current;
}
/**
*
*
* @param array $results An array of Horde_Service_Weather_Station objects.
*
* @return [type] [description]
*/
protected function _parseAutocomplete($results)
{
$return = array();
foreach($results as $result) {
$new = new stdClass();
$new->name = sprintf('%s (%s/%s)', $result->name, $result->lat, $result->lon);
$new->code = $result->code;
$return[] = $new;
}
return $return;
}
/**
* Execute a location search.
*
* @param string $location The location text to search.
*
* @return string The location code result(s).
*/
protected function _searchLocations($location)
{
$url = new Horde_Url(self::API_URL . '/find');
$url = $url->add(array(
'q' => $location,
'type' => 'like')
);
return $this->_makeRequest($url);
}
/**
* Return an array of location search results.
*
* @param stdClass $response The results of a find query.
*
* @return array An array of Horde_Service_Weather_Station objects.
* @throws Horde_Service_Weather_Exception
*/
protected function _parseSearchLocations($response)
{
if (!empty($response->results->error)) {
throw new Horde_Service_Weather_Exception($response->results->error->message);
}
if (!$response->count) {
return array();
}
$results = array();
foreach ($response->list as $result) {
$properties = array(
'name' => $result->name,
'city' => $result->name,
'state' => '',
'country' => $result->sys->country,
'country_name' => '',
'lat' => $result->coord->lat,
'lon' => $result->coord->lon,
'zip' => '',
'code' => $result->id,
);
$results[] = new Horde_Service_Weather_Station($properties);
}
return $results;
}
/**
* Make the remote API call.
*
* @param Horde_Url $url The endpoint.
*
* @return mixed The unserialized results form the remote API call.
* @throws Horde_Service_Weather_Exception
*/
protected function _makeRequest(Horde_Url $url)
{
// Owm returns temperature data in Kelvin by default!
if ($this->_units == Horde_Service_Weather::UNITS_METRIC) {
$url->add('units', 'metric');
} else {
$url->add('units', 'imperial');
}
$url->add(array(
'key' => $this->_key
))->setRaw(true);
$cachekey = md5('hordeweather' . $url);
if ((!empty($this->_cache) &&
!($results = $this->_cache->get($cachekey, $this->_cache_lifetime))) ||
empty($this->_cache)) {
$response = $this->_http->get((string)$url);
if (!$response->code == '200') {
throw new Horde_Service_Weather_Exception($response->code);
}
$results = $response->getBody();
if (!empty($this->_cache)) {
$this->_cache->set($cachekey, $results);
}
}
$results = Horde_Serialize::unserialize($results, Horde_Serialize::JSON);
if (!($results instanceof StdClass)) {
throw new Horde_Service_Weather_Exception(sprintf(
'Error, unable to decode response: %s',
$results));
}
return $results;
}
}
Horde_Service_Weather-2.3.2/lib/Horde/Service/Weather/Station.php 0000664 0001750 0001750 00000005457 12654070567 023011 0 ustar jan jan
* @license http://www.horde.org/licenses/bsd BSD
* @category Horde
* @package Service_Weather
*/
/**
* Horde_Service_Weather_Station class
*
* @author Michael J Rubinsky
* @category Horde
* @package Service_Weather
*
* @property string name The station's common name.
* @property string city The city.
* @property string state The state.
* @property string country The country's iso3166 name (if available).
* @property string country_name The country's common name.
* @property mixed tz The timezone name, or offset from UTC
* depending on the API. @see self::getOffset()
* @property string lat The lattitude (if available).
* @property string lon The longitude (if available).
* @property string zip The postal code.
* @property string code The internal identifier for the API.
*/
class Horde_Service_Weather_Station
{
/**
* Local properties array.
*
* @var array
*/
protected $_properties = array();
/**
* Const'r
*
* @param array $properties The properties for the station.
*/
public function __construct($properties = array())
{
$this->_properties = $properties;
}
/**
* Accessor
*
* @param string $property The property to return.
*
* @return mixed The value of requested property.
*/
public function __get($property)
{
if (isset($this->_properties[$property])) {
return $this->_properties[$property];
}
return '';
}
/**
* Setter.
*
* @param string $property The property name.
* @param mixed $value The value to set $property to.
*/
public function __set($property, $value)
{
$this->_properties[$property] = $value;
}
/**
* Return the CURRENT offset from UTC for this station as provided by the
* API.
*
* @return integer The current offset from UTC.
* @since 1.2.0
*/
public function getOffset()
{
if (!empty($this->_properties['tz']) && is_numeric($this->_properties['tz'])) {
return ($this->tz < 0 ? '-' : '') . gmdate('H:i', floor(abs($this->tz) * 60 * 60));
} elseif (!empty($this->_properties['tz'])) {
try {
$d = new Horde_Date(time(), 'UTC');
$d->setTimezone($this->tz);
return $d->tzOffset();
} catch (Horde_Date_Exception $e) {
}
}
return false;
}
} Horde_Service_Weather-2.3.2/lib/Horde/Service/Weather/Translation.php 0000664 0001750 0001750 00000001326 12654070567 023655 0 ustar jan jan
* @package Service_Weather
*/
class Horde_Service_Weather_Translation extends Horde_Translation_Autodetect
{
/**
* The translation domain
*
* @var string
*/
protected static $_domain = 'Horde_Service_Weather';
/**
* The absolute PEAR path to the translations for the default gettext handler.
*
* @var string
*/
protected static $_pearDirectory = '@data_dir@';
}
Horde_Service_Weather-2.3.2/lib/Horde/Service/Weather/WeatherUnderground.php 0000664 0001750 0001750 00000033637 12654070567 025205 0 ustar jan jan
* @license http://www.horde.org/licenses/bsd BSD
* @category Horde
* @package Service_Weather
*/
/**
* Horde_Service_Weather_WeatherUnderground.
*
* @author Michael J Rubinsky
* @category Horde
* @package Service_Weather
*/
class Horde_Service_Weather_WeatherUnderground extends Horde_Service_Weather_Base
{
const API_URL = 'http://api.wunderground.com';
public $logo = 'weather/wundergroundlogo.png';
/**
* Language to request strings from Google in.
*
* @var string
*/
protected $_language = 'en';
/**
* @see Horde_Service_Weather::$iconMap
*/
public $iconMap = array(
'chanceflurries' => '15.png',
'chancerain' => '11.png',
'chancesleet' => '8.png',
'chancesnow' => '14.png',
'chancetstorms' => '3.png',
'clear' => '32.png',
'cloudy' => '26.png',
'flurries' => '14.png',
'fog' => '20.png',
'hazy' => '21.png',
'mostlycloudy' => '28.png',
'mostlysunny' => '34.png',
'partlycloudy' => '30.png',
'partlysunny' => '30.png',
'sleet' => '10.png',
'rain' => '12.png',
'snow' => '16.png',
'sunny' => '32.png',
'tstorms' => '3.png',
// Nighttime
'nt_chanceflurries' => '46.png',
'nt_chancerain' => '45.png',
'nt_chancesleet' => '10.png',
'nt_chancesnow' => '46.png',
'nt_chancetstorms' => '45.png',
'nt_clear' => '31.png',
'nt_cloudy' => '26.png',
'nt_flurries' => '46.png',
'nt_fog' => '20.png',
'nt_hazy' => '21.png',
'nt_mostlycloudy' => '45.png',
'nt_partlycloudy' => '29.png',
'nt_sleet' => '10.png',
'nt_rain' => '45.png',
'nt_snow' => '46.png',
'nt_tstorms' => '47.png'
);
/**
* Constructor.
*
* @param array $params Parameters:
* - cache: (Horde_Cache) Optional Horde_Cache object.
* - cache_lifetime: (integer) Lifetime of cached data, if caching.
* - http_client: (Horde_Http_Client) Required http client object.
* - apikey: (string) Require api key for Wwo.
*
* @return Horde_Service_Weather_WeatherUnderground
*/
public function __construct(array $params = array())
{
// Check required api key parameters here...
if (empty($params['apikey'])) {
throw new InvalidArgumentException('Missing required API Key parameter.');
}
if (!empty($params['language'])) {
$this->_language = $params['language'];
}
$this->_apiKey = $params['apikey'];
unset($params['apikey']);
parent::__construct($params);
}
/**
* Obtain the current observations.
*
* @see Horde_Service_Weather_Current_Base::getCurrentConditions()
*
* @return Horde_Service_Weather_Current_WeatherUnderground.
*/
public function getCurrentConditions($location)
{
$this->_getCommonElements(rawurlencode($location), !empty($this->_lastLength) ? $this->_lastLength : null);
return $this->_current;
}
/**
* Obtain the forecast for the current location.
*
* @see Horde_Service_Weather_Base::getForecast()
*
* @return Horde_Service_Weather_Forecast_WeatherUnderground
*/
public function getForecast(
$location,
$length = Horde_Service_Weather::FORECAST_3DAY,
$type = Horde_Service_Weather::FORECAST_TYPE_STANDARD)
{
$this->_getCommonElements(rawurlencode($location), $length);
return $this->_forecast;
}
public function getAlerts($location)
{
$this->_getCommonElements(rawurlencode($location), !empty($this->_lastLength) ? $this->_lastLength : null);
return $this->_alerts;
}
/**
* Return the URL to a (possibly animated) radar image.
*
* @param string $location The location
*
* @return string|boolean The Url, or false if not available.
*/
public function getRadarImageUrl($location)
{
$this->_getCommonElements(rawurlencode($location), !empty($this->_lastLength) ? $this->_lastLength : null);
return $this->_radar;
}
/**
* Search for a valid location code.
*
* @see Horde_Service_Weather_Base::searchLocations()
*/
public function searchLocations($location, $type = Horde_Service_Weather::SEARCHTYPE_STANDARD)
{
switch ($type) {
case Horde_Service_Weather::SEARCHTYPE_STANDARD:
case Horde_Service_Weather::SEARCHTYPE_ZIP:
case Horde_Service_Weather::SEARCHTYPE_CITYSTATE:
return $this->_parseSearchLocations($this->_searchLocations(rawurlencode($location)));
case Horde_Service_Weather::SEARCHTYPE_IP:
return $this->_parseSearchLocations($this->_getLocationByIp(rawurlencode($location)));
}
}
/**
* Return an autocomplete search response.
*
* @see Horde_Service_Weather_Base::autocompleteLocation()
*/
public function autocompleteLocation($search)
{
$url = new Horde_Url('http://autocomplete.wunderground.com/aq');
$url->add(array('query' => $search, 'format' => 'JSON'));
return $this->_parseAutocomplete($this->_makeRequest($url));
}
/**
* Get array of supported forecast lengths.
*
* @return array The array of supported lengths.
*/
public function getSupportedForecastLengths()
{
return array(
3 => Horde_Service_Weather::FORECAST_3DAY,
5 => Horde_Service_Weather::FORECAST_5DAY,
7 => Horde_Service_Weather::FORECAST_7DAY,
10 => Horde_Service_Weather::FORECAST_10DAY
);
}
/**
* Perform an IP location search.
*
* @param string $ip The IP address to use.
*
* @return string The location code.
*/
protected function _getLocationByIp($ip)
{
if ($this->_ipIsUnique($ip)) {
return $this->_makeRequest(
self::API_URL . '/api/' . $this->_apiKey
. '/geolookup/q/autoip.json?geo_ip=' . $ip);
} else {
return $this->_makeRequest(
self::API_URL . '/api/' . $this->_apiKey
. '/geolookup/q/autoip.json');
}
}
/**
* Execute a location search.
*
* @param string $location The location text to search.
*
* @return string The location code result(s).
*/
protected function _searchLocations($location)
{
return $this->_makeRequest(self::API_URL . '/api/' . $this->_apiKey
. '/geolookup/q/' . $location . '.json');
}
/**
* Weather Underground allows requesting multiple features per request,
* and only counts it as a single request against your API key. So we trade
* a bit of request time/traffic for a smaller number of requests to obtain
* information for e.g., a typical weather portal display.
*/
protected function _getCommonElements($location, $length = null)
{
$length = empty($length) ? Horde_Service_Weather::FORECAST_10DAY : $length;
if (!empty($this->_forecast) && $location == $this->_lastLocation
&& $this->_lastLength >= $length) {
if ($this->_lastLength > $length) {
$this->_forecast->limitLength($length);
}
return;
}
$this->_lastLength = $length;
$this->_lastLocation = $location;
switch ($length) {
case Horde_Service_Weather::FORECAST_3DAY:
$l = 'forecast';
break;
case Horde_Service_Weather::FORECAST_5DAY:
case Horde_Service_Weather::FORECAST_7DAY:
$l = 'forecast7day';
break;
case Horde_Service_Weather::FORECAST_10DAY:
$l = 'forecast10day';
break;
}
$url = self::API_URL . '/api/' . $this->_apiKey
. '/geolookup/conditions/animatedradar/alerts/'
. $l . '/astronomy/q/' . $location . '.json';
$results = $this->_makeRequest($url, $this->_cache_lifetime);
$station = $this->_parseStation($results->location);
$this->_current = $this->_parseCurrent($results->current_observation);
if (!empty($results->alerts)) {
$this->_alerts = $this->_parseAlerts($results->alerts);
}
$astronomy = $results->moon_phase;
$date = clone $this->_current->time;
$date->hour = $astronomy->sunrise->hour;
$date->min = $astronomy->sunrise->minute;
$date->sec = 0;
$station->sunrise = $date;
$station->sunset = clone $date;
$station->sunset->hour = $astronomy->sunset->hour;
$station->sunset->min = $astronomy->sunset->minute;
// Station information doesn't include any type of name string, so
// get it from the currentConditions request.
$station->name = $results->current_observation->display_location->full;
$this->_station = $station;
$this->_forecast = $this->_parseForecast($results->forecast);
$this->_forecast->limitLength($length);
$this->link = $results->current_observation->image->link;
$this->title = $results->current_observation->image->title;
// Radar
if (isset($results->radar->image_url)) {
$this->_radar = $results->radar->image_url;
}
}
/**
* Parses the JSON response for a location request into a station object.
*
* @param StdClass $station The response from a Location request.
*
* @return Horde_Service_Weather_Station
*/
protected function _parseStation($station)
{
// @TODO: Create a subclass of Station for wunderground, parse the
// "close stations" and "pws" properties - allow for things like
// displaying other, nearby weather station conditions etc...
$properties = array(
'city' => $station->city,
'state' => $station->state,
'country' => $station->country_iso3166,
'country_name' => $station->country_name,
'tz' => isset($station->tz_long) ? $station->tz_long : '',
'lat' => isset($station->lat) ? $station->lat : '',
'lon' => isset($station->lon) ? $station->lon : '',
'zip' => isset($station->zip) ? $station->zip : '',
'code' => str_replace('/q/', '', $station->l)
);
return new Horde_Service_Weather_Station($properties);
}
/**
* Parses the forecast data.
*
* @param stdClass $forecast The result of the forecast request.
*
* @return Horde_Service_Weather_Forecast_WeatherUnderground The forecast.
*/
protected function _parseForecast($forecast)
{
return new Horde_Service_Weather_Forecast_WeatherUnderground(
(array)$forecast, $this);
}
/**
* Parses astronomy information. Returned as an array since this will be
* added to the station information.
*
* @param {[type]} $astronomy [description]
* @return {[type]}
*/
protected function _parseAstronomy($astronomy)
{
// For now, just cast to array and pass back, we need to normalize
// at least the moon data. (Given in percent illuminated and age -
// need to parse that into phases.)
return (array)$astronomy;
}
/**
* Parse the current_conditions response.
*
* @param stdClass $current The current_condition request response object
*
* @return Horde_Service_Weather_Current
*/
protected function _parseCurrent($current)
{
// The Current object takes care of the parsing/mapping.
return new Horde_Service_Weather_Current_WeatherUnderground((array)$current, $this);
}
protected function _parseSearchLocations($response)
{
if (!empty($response->response->error)) {
throw new Horde_Service_Weather_Exception($response->response->error->description);
}
if (!empty($response->response->results)) {
$results = array();
foreach ($response->response->results as $location) {
$results[] = $this->_parseStation($location);
}
return $results;
} else {
return $this->_parseStation($response->location);
}
}
protected function _parseAutocomplete($results)
{
$return = array();
foreach($results->RESULTS as $result) {
$new = new stdClass();
$new->name = $result->name;
$new->code = $result->l;
$return[] = $new;
}
return $return;
}
protected function _parseAlerts($alerts)
{
$alerts_ob = new Horde_Service_Weather_Alerts_WeatherUnderground($alerts, $this);
return $alerts_ob->getAlerts();
}
protected function _makeRequest($url, $lifetime = 86400)
{
$cachekey = md5('hordeweather' . $url);
if ((!empty($this->_cache) && !$results = $this->_cache->get($cachekey, $lifetime)) ||
empty($this->_cache)) {
$url = new Horde_Url($url);
$response = $this->_http->get((string)$url);
if (!$response->code == '200') {
throw new Horde_Service_Weather_Exception($response->code);
}
$results = $response->getBody();
if (!empty($this->_cache)) {
$this->_cache->set($cachekey, $results);
}
}
$results = Horde_Serialize::unserialize($results, Horde_Serialize::JSON);
if (!($results instanceof StdClass)) {
throw new Horde_Service_Weather_Exception('Error, unable to decode response.');
}
return $results;
}
}
Horde_Service_Weather-2.3.2/lib/Horde/Service/Weather/WeatherUnderground_Strings.php 0000664 0001750 0001750 00000007113 12654070567 026704 0 ustar jan jan
* @license http://www.horde.org/licenses/bsd BSD
* @category Horde
* @package Service_Weather
*/
/**
* Horde_Service_Weather_Wwo
*
* @author Michael J Rubinsky
* @category Horde
* @package Service_Weather
*/
class Horde_Service_Weather_Wwo extends Horde_Service_Weather_Base
{
const API_URL = 'http://api.worldweatheronline.com/free/v1/weather.ashx';
const SEARCH_URL = 'http://api.worldweatheronline.com/free/v1/search.ashx';
const API_URL_v2 = 'https://api.worldweatheronline.com/free/v2/weather.ashx';
const SEARCH_URL_v2 = 'https://api.worldweatheronline.com/free/v2/search.ashx';
/**
* @see Horde_Service_Weather_Base::$title
* @var string
*/
public $title = 'World Weather Online';
/**
* @see Horde_Service_Weather_Base::$link
* @var string
*/
public $link = 'http://worldweatheronline.com';
/**
* @see Horde_Service_Weather::$iconMap
*/
public $iconMap = array(
'wsymbol_0001_sunny' => '32.png',
'wsymbol_0002_sunny_intervals' => '30.png',
'wsymbol_0003_white_cloud' => '26.png',
'wsymbol_0004_black_low_cloud' => '26.png',
'wsymbol_0006_mist' => '34.png',
'wsymbol_0007_fog' => '20.png',
'wsymbol_0008_clear_sky_night' => '33.png',
'wsymbol_0009_light_rain_showers' => '11.png',
'wsymbol_0010_heavy_rain_showers' => '12.png',
'wsymbol_0011_light_snow_showers' => '14.png',
'wsymbol_0012_heavy_snow_showers' => '16.png',
'wsymbol_0013_sleet_showers' => '7.png',
'wsymbol_0016_thundery_showers' => '0.png',
'wsymbol_0017_cloudy_with_light_rain' => '11.png',
'wsymbol_0018_cloudy_with_heavy_rain' => '12.png',
'wsymbol_0019_cloudy_with_light_snow' => '13.png',
'wsymbol_0020_cloudy_with_heavy_snow' => '16.png',
'wsymbol_0021_cloudy_with_sleet' => '8.png',
'wsymbol_0024_thunderstorms' => '0.png',
'wsymbol_0025_light_rain_showers_night' => '40.png',
'wsymbol_0026_heavy_rain_showers_night' => '30.png',
'wsymbol_0027_light_snow_showers_night' => '41.png',
'wsymbol_0028_heavy_snow_showers_night' => '42.png',
'wsymbol_0029_sleet_showers_night' => '7.png',
'wsymbol_0032_thundery_showers_night' => '47.png',
'wsymbol_0033_cloudy_with_light_rain_night' => '45.png',
'wsymbol_0034_cloudy_with_heavy_rain_night' => '45.png',
'wsymbol_0035_cloudy_with_light_snow_night' => '46.png',
'wsymbol_0036_cloudy_with_heavy_snow_night' => '46.png',
'wsymbol_0037_cloudy_with_sleet_night' => '8.png',
'wsymbol_0040_thunderstorms_night' => '47.png'
);
/**
* Wwo API key.
*
* @var string
*/
protected $_key;
/**
* API Version
*
* @var integer
*/
protected $_version;
/**
* Constructor.
*
* @param array $params Parameters:
* - cache: (Horde_Cache) Optional Horde_Cache object.
* - cache_lifetime: (integer) Lifetime of cached data, if caching.
* - http_client: (Horde_Http_Client) Required http client object.
* - apikey: (string) Require api key for Wwo.
* - apiVersion: (integer) Version of the API to use.
* Defaults to v1 for BC reasons.
*
* @return Horde_Service_Weather_Wwo
*/
public function __construct(array $params = array())
{
// Check required api key parameters here...
if (empty($params['apikey'])) {
throw new InvalidArgumentException('Missing required API Key parameter.');
}
$this->_version = empty($params['apiVersion']) ? 1 : $params['apiVersion'];
$this->_key = $params['apikey'];
unset($params['apikey']);
parent::__construct($params);
}
/**
* Obtain the current observations.
*
* @see Horde_Service_Weather_Base::getCurrentConditions
*
* @return Horde_Service_Weather_Current_Wwo
*/
public function getCurrentConditions($location)
{
$this->_getCommonElements($location);
return $this->_current;
}
/**
* Obtain the forecast for the current location.
*
* @see Horde_Service_Weather_Base::getForecast
*/
public function getForecast(
$location,
$length = Horde_Service_Weather::FORECAST_3DAY,
$type = Horde_Service_Weather::FORECAST_TYPE_STANDARD)
{
$this->_getCommonElements($location);
return $this->_forecast;
}
/**
* Search for a valid location code.
*
* @see Horde_Service_Weather_Base::searchLocations
*/
public function searchLocations($location, $type = Horde_Service_Weather::SEARCHTYPE_STANDARD)
{
switch ($type) {
case Horde_Service_Weather::SEARCHTYPE_STANDARD:
case Horde_Service_Weather::SEARCHTYPE_IP:
return $this->_parseSearchLocations($this->_searchLocations($location));
}
}
/**
* Return an autocomplete request result.
*
* @see Horde_Service_Weather_Base::autocompleteLocation
*/
public function autocompleteLocation($search)
{
$url = new Horde_Url($this->_version == 1 ? self::SEARCH_URL : self::SEARCH_URL_v2);
$url->add(array(
'q' => $search,
'format' => 'json',
'num_of_results' => 25));
return $this->_parseAutocomplete($this->_makeRequest($url));
}
/**
* Return the supported forecast lengths.
*
* @see Horde_Service_Weather_Base::getSupportedForecastLengths
*/
public function getSupportedForecastLengths()
{
return array(
3 => Horde_Service_Weather::FORECAST_3DAY,
5 => Horde_Service_Weather::FORECAST_5DAY
);
}
/**
* Populates some common data used by forecasts and current conditions.
* Weather Underground allows requesting multiple features per request,
* and only counts it as a single request against your API key. So we trade
* a bit of request time/traffic for a smaller number of requests to obtain
* information for e.g., a typical weather portal display.
*
* @param string $location The location identifier.
* @param integer $length The forecast length.
*/
protected function _getCommonElements($location, $length = Horde_Service_Weather::FORECAST_5DAY)
{
if (!empty($this->_current) && $location == $this->_lastLocation
&& $this->_lastLength == $length) {
return;
}
$this->_lastLength = $length;
$this->_lastLocation = $location;
$url = new Horde_Url($this->_version == 1 ? self::API_URL : self::API_URL_v2);
// Not sure why, but Wwo chokes if we urlencode the location?
$url->add(array(
'q' => $location,
'num_of_days' => $length,
'includeLocation' => 'yes',
'extra' => 'localObsTime')
);
if ($this->_version == 1) {
$url->add(array(
'timezone' => 'yes')
);
}
// V2 of the API only returns hourly data, so ask for 24 hour avg.
// @todo Revisit when we support hourly forecast data.
if ($this->_version == 2) {
$url->add(array(
'tp' => 24,
'showlocaltime' => 'yes',
'showmap' => 'yes')
);
}
$results = $this->_makeRequest($url);
// Use the minimum station data provided by forecast request to
// fetch the full station data.
$station = $this->_parseStation($results->data->nearest_area[0]);
$station = $this->searchLocations($station->lat . ',' . $station->lon);
// Hack some data to allow UTC observation time to be returned.
$results->data->current_condition[0]->date = new Horde_Date($results->data->current_condition[0]->localObsDateTime);
$results->data->current_condition[0]->date->hour += -$station->getOffset();
// Parse it.
$this->_current = $this->_parseCurrent($results->data->current_condition);
// Sunrise/Sunset
// @todo - this is now available in the forecast section in v2
$date = $this->_current->time;
$station->sunset = new Horde_Date(
date_sunset(
$date->timestamp(),
SUNFUNCS_RET_TIMESTAMP,
$station->lat,
$station->lon)
);
$station->sunrise = new Horde_Date(
date_sunrise(
$date->timestamp(),
SUNFUNCS_RET_TIMESTAMP,
$station->lat,
$station->lon)
);
$station->time = (string)$date;
$this->_station = $station;
$this->_forecast = $this->_parseForecast($results->data->weather);
}
/**
* Parses the JSON response for a location request into a station object.
*
* @param StdClass $station The response from a Location request.
*
* @return Horde_Service_Weather_Station
*/
protected function _parseStation($station)
{
$properties = array(
'name' => $station->areaName[0]->value . ', ' . $station->region[0]->value,
'city' => $station->areaName[0]->value,
'state' => $station->region[0]->value,
'country' => $station->country[0]->value,
'country_name' => '',
'lat' => $station->latitude,
'lon' => $station->longitude,
'zip' => '',
'code' => $station->latitude . ',' . $station->longitude
);
if (isset($station->timezone)) {
// Only the *current* UTC offset is provided, with no indication
// if we are in DST or not.
$properties['tz'] = $station->timezone[0]->offset;
}
return new Horde_Service_Weather_Station($properties);
}
/**
* Parses the forecast data.
*
* @param stdClass $forecast The result of the forecast request.
*
* @return Horde_Service_Weather_Forecast_Wwo The forecast.
*/
protected function _parseForecast($forecast)
{
$forecast = $this->_version == 1
? new Horde_Service_Weather_Forecast_Wwo($forecast, $this)
: new Horde_Service_Weather_Forecast_Wwov2($forecast, $this);
return $forecast;
}
/**
* Parse the current_conditions response.
*
* @param stdClass $current The current_condition request response object
*
* @return Horde_Service_Weather_Current
*/
protected function _parseCurrent($current)
{
// The Current object takes care of the parsing/mapping.
$current = new Horde_Service_Weather_Current_Wwo($current[0], $this);
return $current;
}
protected function _parseAutocomplete($results)
{
$return = array();
if (!empty($results->search_api->result)) {
foreach($results->search_api->result as $result) {
if (!empty($result->region[0]->value)) {
$new = new stdClass();
$new->name = $result->areaName[0]->value . ', ' . $result->region[0]->value;
$new->code = $result->latitude . ',' . $result->longitude;
$return[] = $new;
}
}
}
return $return;
}
/**
* Execute a location search.
*
* @param string $location The location text to search.
*
* @return string The location code result(s).
*/
protected function _searchLocations($location)
{
$url = new Horde_Url($this->_version == 1 ? self::SEARCH_URL : self::SEARCH_URL_v2);
$url = $url->add(array(
'timezone' => 'yes',
'q' => $location,
'num_of_results' => 10));
return $this->_makeRequest($url);
}
protected function _parseSearchLocations($response)
{
if (!empty($response->results->error)) {
throw new Horde_Service_Weather_Exception($response->results->error->message);
}
// Wwo's location search is pretty useless. It *always* returns multiple
// matches, even if you pass an explicit identifier. We need to ignore
// these, and hope for the best.
if (!empty($response->search_api->result)) {
return $this->_parseStation($response->search_api->result[0]);
}
return array();
}
/**
* Make the remote API call.
*
* @param Horde_Url $url The endpoint.
*
* @return mixed The unserialized results form the remote API call.
* @throws Horde_Service_Weather_Exception
*/
protected function _makeRequest(Horde_Url $url)
{
$url->add(array(
'format' => 'json',
'key' => $this->_key
))->setRaw(true);
$cachekey = md5('hordeweather' . $url);
if ((!empty($this->_cache) &&
!($results = $this->_cache->get($cachekey, $this->_cache_lifetime))) ||
empty($this->_cache)) {
$response = $this->_http->get((string)$url);
if (!$response->code == '200') {
throw new Horde_Service_Weather_Exception($response->code);
}
$results = $response->getBody();
if (!empty($this->_cache)) {
$this->_cache->set($cachekey, $results);
}
}
$results = Horde_Serialize::unserialize($results, Horde_Serialize::JSON);
if (!($results instanceof StdClass)) {
throw new Horde_Service_Weather_Exception(sprintf(
'Error, unable to decode response: %s',
$results));
}
return $results;
}
}
Horde_Service_Weather-2.3.2/lib/Horde/Service/Weather/Wwo_Strings.php 0000664 0001750 0001750 00000002605 12654070567 023645 0 ustar jan jan
* @license http://www.horde.org/licenses/bsd BSD
* @category Horde
* @package Service_Weather
*/
/**
* Horde_Service_Weather class
*
* @author Michael J Rubinsky
* @category Horde
* @package Service_Weather
*/
class Horde_Service_Weather
{
/** Forecast length constants **/
const FORECAST_3DAY = 3;
const FORECAST_5DAY = 5;
const FORECAST_7DAY = 7;
const FORECAST_10DAY = 10;
/** Standard forecast summary **/
const FORECAST_TYPE_STANDARD = 1;
/** Detailed forecast, contains a day/night component for each day **/
const FORECAST_TYPE_DETAILED = 2;
/** Hourly forecast **/
const FORECAST_TYPE_HOURLY = 3;
const FORECAST_FIELD_WIND = 'wind';
const FORECAST_FIELD_PRECIPITATION = 'pop';
const FORECAST_FIELD_HUMIDITY = 'humidity';
const FORECAST_FIELD_ACCUMULATION = 'accum';
/** Unit constants **/
const UNITS_STANDARD = 1;
const UNITS_METRIC = 2;
/** Conversion constants **/
const CONVERSION_MPH_TO_KNOTS = 0.868976242;
const CONVERSION_MPH_TO_KPH = 1.609344;
const CONVERSION_KPH_TO_MPH = 0.621371192;
const CONVERSION_MB_TO_INCHES = 0.0295301;
/** Location search types **/
const SEARCHTYPE_STANDARD = 1;
const SEARCHTYPE_IP = 2;
const SEARCHTYPE_ZIP = 3;
const SEARCHTYPE_CITYSTATE = 4;
/**
* Utility function to return textual cardinal compass directions from degress.
*
* @param integer $degree The degree direction (0 - 360).
*
* @return string The cardinal direction.
* @since 2.3.0
*/
public static function degToDirection($degree)
{
$cardinal = array('N', 'NNE', 'NE', 'ENE', 'E', 'ESE', 'SE', 'SSE', 'S', 'SSW', 'SW', 'WSW', 'W', 'WNW', 'NW', 'NNW');
$deg_delta = (int)($degree/22.5 + .5);
return $cardinal[$deg_delta % 16];
}
} Horde_Service_Weather-2.3.2/locale/de/LC_MESSAGES/Horde_Service_Weather.mo 0000664 0001750 0001750 00000032346 12654070567 024217 0 ustar jan jan t 9 / > N ] u
% 6
C Q b o t
,
@ K
^ i | "
3 > N g
s ~ # # > b u
0 < H [ n
0 I [ s "
& 8 K W # j #
3 A
U ` r
+ 3 _ ( } +
) 7
N
\ j w y }
&