Files
server/usr/share/psa-horde/timeobjects/lib/Driver/Weather.php
2026-01-07 20:52:11 +01:00

246 lines
8.2 KiB
PHP

<?php
/**
* TimeObjects driver for exposing weatherunderground information via the
* listTimeObjects API.
*
* Copyright 2011-2017 Horde LLC (http://www.horde.org/)
*
* @author Michael J Rubinsky <mrubinsk@horde.org>
* @license http://www.horde.org/licenses/bsd BSD
* @category Horde
* @package TimeObjects
*/
class TimeObjects_Driver_Weather extends TimeObjects_Driver_Base
{
protected $_forecastDays = Horde_Service_Weather::FORECAST_7DAY;
protected $_location;
public function __construct(array $params)
{
global $registry, $prefs;
// Assume if it's passed in, we know it's valid.
if (!empty($params['location'])) {
$this->_location = $params['location'];
} else {
$this->_findLocation();
}
parent::__construct($params);
}
/**
* Ensures that we meet all requirements to use this time object
*
* @return boolean
*/
public function ensure()
{
if (empty($GLOBALS['conf']['weather']['provider']) || empty($this->_location)) {
return false;
}
try {
$this->_create();
} catch (Exception $e) {
return false;
}
return true;
}
/**
*
* @param Horde_Date $start The start time of the period
* @param Horde_Date $end The end time of the period
*
* @return array of listTimeObjects arrays.
*/
public function listTimeObjects(Horde_Date $start = null, Horde_Date $end = null)
{
global $conf, $prefs;
// No need to continue if the forecast days are not in the current
// range.
$forecast_start = new Horde_Date(time());
$forecast_end = clone $forecast_start;
$forecast_end->mday += 7;
if ($end->before($forecast_start) || $start->after($forecast_end)) {
return array();
}
$weather = $this->_create();
$lengths = $weather->getSupportedForecastLengths();
try {
$units = $weather->getUnits($weather->units);
$forecast = $weather->getForecast($this->_location, max(array_keys($lengths)));
$current = $weather->getCurrentConditions($this->_location);
} catch (Horde_Service_Weather_Exception $e) {
throw new Timeobjects_Exception($e);
}
$objects = array();
foreach ($forecast as $data) {
$day = $data->date;
$day->hour = 0;
$day->min = 0;
$day->sec = 0;
$day_end = clone $day;
$day_end->mday++;
$title = sprintf(
'%s %d°%s/%d°%s',
$data->conditions,
$data->high,
$units['temp'],
$data->low,
$units['temp']
);
// Deterine what information we have to display.
$pop = $data->precipitation_percent === false ? _("N/A") : ($data->precipitation_percent . '%');
if ($forecast->detail == Horde_Service_Weather::FORECAST_TYPE_STANDARD) {
if ($data->humidity !== false && $data->wind_direction !== false) {
$description = sprintf(
_("Conditions: %s\nHigh temperature: %d%s\nPrecipitation: %s\nHumidity: %d%%\nWinds: From the %s at %d%s"),
_($data->conditions),
$data->high,
'°' . $units['temp'],
$pop,
$data->humidity,
$data->wind_direction,
$data->wind_speed,
$units['wind']
);
} else {
$description = sprintf(
_("Conditions: %s\nHigh temperature: %d%s\nPrecipitation: %s\n"),
_($data->conditions),
$data->high,
'°' . $units['temp'],
$pop
);
}
} elseif ($forecast->detail == Horde_Service_Weather::FORECAST_TYPE_DETAILED) {
// @TODO
// No drivers support this yet. AccuWeather will, and possibly
// wunderground if they accept my request.
}
$station = $weather->getStation();
$body = sprintf(
_("Location: %s"),
$weather->getStation()->name
);
if (!empty($weather->getStation()->sunrise)) {
$body .= sprintf(
_("Sunrise: %s\nSunset: %s\n"),
$weather->getStation()->sunrise,
$weather->getStation()->sunset
);
}
$body .= "\n" . $description;
$objects[] = array(
'id' => $day->timestamp(), //???
'title' => $title,
'description' => $body,
'start' => $day->strftime('%Y-%m-%dT00:00:00'),
'end' => $day_end->strftime('%Y-%m-%dT00:00:00'),
'recurrence' => Horde_Date_Recurrence::RECUR_NONE,
'params' => array(),
'link' => new Horde_Url('#'),
'icon' => (string)Horde_Themes::img('weather/23x23/' . $data->icon)
);
$day->mday++;
}
return $objects;
}
protected function _findLocation()
{
global $registry, $injector;
// First use the location pref, then turba's "own" contact, followed
// general IP location?
$identity = $injector
->getInstance('Horde_Core_Factory_Identity')
->create();
if (!($location = $identity->getValue('location')) &&
$registry->hasInterface('contacts')) {
try {
$contact = $GLOBALS['registry']->contacts->ownContact();
} catch (Exception $e) {
}
if (!empty($contact['homeCountry'])) {
$country = $contact['homeCountry'];
} elseif (!empty($contact['workCountry'])) {
$country = $contact['workCountry'];
}
if (!empty($contact['homeCity'])) {
$location = $contact['homeCity']
. (!empty($contact['homeProvince']) ? ', ' . $contact['homeProvince'] : '')
. (!empty($contact['homeCountry']) ? ', ' . $contact['homeCountry'] : '');
} elseif (!empty($contact['workCity'])) {
$location = $contact['workCity']
. (!empty($contact['workProvince']) ? ', ' . $contact['workProvince'] : '')
. (!empty($contact['workCountry']) ? ', ' . $contact['workCountry'] : '');
}
}
// Ensure we have a valid location code for the location.
try {
$driver = $this->_create();
} catch (Exception $e) {
return;
}
if (!empty($location)) {
try {
$location = $driver->searchLocations($location);
} catch (Horde_Service_Weather_Exception $e) {
Horde::log($e, 'ERR');
throw new Timeobjects_Exception($e);
}
} else {
try {
$location = $driver->searchLocations(
$GLOBALS['browser']->getIPAddress(),
Horde_Service_Weather::SEARCHTYPE_IP);
} catch (Horde_Service_Weather_Exception $e) {
return;
}
}
if (is_array($location) && count($location)) {
$location = $location[0];
}
if ($location) {
$this->_location = $location->code;
}
}
/**
* Private factory for weather driver.
*
* @return Horde_Service_Weather_Base
*/
protected function _create()
{
try {
$driver = $GLOBALS['injector']->getInstance('Horde_Weather');
} catch (Exception $e) {
throw new Timeobjects_Exception($e);
}
// Suggest units, but the driver may override this (like Google).
$country = substr($GLOBALS['language'], -2);
$driver->units = $country == 'US'
? Horde_Service_Weather::UNITS_STANDARD
: Horde_Service_Weather::UNITS_METRIC;
return $driver;
}
}