From: Michael J. Rubinsky Date: Sun, 7 Jun 2009 16:59:19 +0000 (-0400) Subject: Add a timeobjects API-only application for providing a way to expose X-Git-Url: https://git.internetallee.de/?a=commitdiff_plain;h=65b7252e2bf34a2424bf00d5e9d72240a02afaac;p=horde.git Add a timeobjects API-only application for providing a way to expose data via the listTimeObjects API. Currently only a Weather driver is available. --- diff --git a/timeobjects/config/conf.php b/timeobjects/config/conf.php new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/timeobjects/config/conf.php @@ -0,0 +1 @@ + diff --git a/timeobjects/config/prefs.php b/timeobjects/config/prefs.php new file mode 100644 index 000000000..e69de29bb diff --git a/timeobjects/config/timeobjects.php.registry.d b/timeobjects/config/timeobjects.php.registry.d new file mode 100644 index 000000000..f18db03d1 --- /dev/null +++ b/timeobjects/config/timeobjects.php.registry.d @@ -0,0 +1,9 @@ +applications['timeobjects'] = array( + 'fileroot' => $this->applications['kronolith']['fileroot'] . '/../timeobjects', + 'status' => 'hidden', + 'name' => _("Time Objects"), + 'provides' => 'timeobjects' +); \ No newline at end of file diff --git a/timeobjects/lib/Driver.php b/timeobjects/lib/Driver.php new file mode 100644 index 000000000..b59768b8c --- /dev/null +++ b/timeobjects/lib/Driver.php @@ -0,0 +1,35 @@ +_params = array_merge($params, $this->_params); + } + + /** + * @abstract + * @param $start + * @param $end + * @return unknown_type + */ + public function listTimeObjects($start, $end) + { + } + + public function factory($name, $params = array()) + { + $class = 'TimeObjects_Driver_' . basename($name); + if (class_exists($class)) { + $driver = &new $class($params); + } else { + $driver = PEAR::raiseError(sprintf(_("Unable to load the definition of %s."), $class)); + } + + return $driver; + } +} \ No newline at end of file diff --git a/timeobjects/lib/Driver/Weather.php b/timeobjects/lib/Driver/Weather.php new file mode 100644 index 000000000..509d5e09f --- /dev/null +++ b/timeobjects/lib/Driver/Weather.php @@ -0,0 +1,153 @@ + + * @package TimeObjects + */ +class TimeObjects_Driver_Weather extends TimeObjects_Driver +{ + protected $_params = array('location' => '08080', + 'units' => 'standard', + 'days' => 5); + + /** + * + * @param mixed $start The start time of the period + * @param mixed $time The end time of the period + * + * @return array of listTimeObjects arrays. + */ + public function listTimeObjects($start = null, $time = null) + { + global $conf; + + if (!class_exists('Services_Weather') || !class_exists('Cache')) { + throw new TimeObjects_Exception('Services_Weather or PEAR Cache Classes not found.'); + } + + $options = array(); + if (!empty($conf['http']['proxy']['proxy_host'])) { + $proxy = 'http://'; + if (!empty($conf['http']['proxy']['proxy_user'])) { + $proxy .= urlencode($conf['http']['proxy']['proxy_user']); + if (!empty($conf['http']['proxy']['proxy_pass'])) { + $proxy .= ':' . urlencode($conf['http']['proxy']['proxy_pass']); + } + $proxy .= '@'; + } + $proxy .= $conf['http']['proxy']['proxy_host']; + if (!empty($conf['http']['proxy']['proxy_port'])) { + $proxy .= ':' . $conf['http']['proxy']['proxy_port']; + } + + $options['httpProxy'] = $proxy; + } + + if (empty($this->_params['location'])) { + throw new TimeObjects_Exception(_("No location is set.")); + } + + $weatherDotCom = &Services_Weather::service('WeatherDotCom', $options); + $weatherDotCom->setAccountData( + (isset($conf['weatherdotcom']['partner_id']) ? $conf['weatherdotcom']['partner_id'] : ''), + (isset($conf['weatherdotcom']['license_key']) ? $conf['weatherdotcom']['license_key'] : '')); + + $cacheDir = Horde::getTempDir(); + if (!$cacheDir) { + throw new TimeObjects_Exception(_("No temporary directory available for cache.")); + } else { + $weatherDotCom->setCache('file', array('cache_dir' => ($cacheDir . '/'))); + } + $weatherDotCom->setDateTimeFormat('m.d.Y', 'H:i'); + $weatherDotCom->setUnitsFormat($this->_params['units']); + $units = $weatherDotCom->getUnitsFormat(); + + // If the user entered a zip code for the location, no need to + // search (weather.com accepts zip codes as location IDs). + // The location ID should already have been validated in + // getParams. + // + // @TODO: These need to all be changed to use exceptions + $search = (preg_match('/\b(?:\\d{5}(-\\d{5})?)|(?:[A-Z]{4}\\d{4})\b/', + $this->_params['location'], $matches) ? + $matches[0] : + $weatherDotCom->searchLocation($this->_params['location'])); + if (is_a($search, 'PEAR_Error')) { + switch ($search->getCode()) { + case SERVICES_WEATHER_ERROR_SERVICE_NOT_FOUND: + throw new TimeObjects_Exception(_("Requested service could not be found.")); + case SERVICES_WEATHER_ERROR_UNKNOWN_LOCATION: + throw new TimeObjects_Exception(_("Unknown location provided.")); + case SERVICES_WEATHER_ERROR_WRONG_SERVER_DATA: + throw new TimeObjects_Exception(_("Server data wrong or not available.")); + case SERVICES_WEATHER_ERROR_CACHE_INIT_FAILED: + throw new TimeObjects_Exception(_("Cache init was not completed.")); + case SERVICES_WEATHER_ERROR_DB_NOT_CONNECTED: + throw new TimeObjects_Exception(_("MetarDB is not connected.")); + case SERVICES_WEATHER_ERROR_UNKNOWN_ERROR: + throw new TimeObjects_Exception(_("An unknown error has occured.")); + case SERVICES_WEATHER_ERROR_NO_LOCATION: + throw new TimeObjects_Exception(_("No location provided.")); + case SERVICES_WEATHER_ERROR_INVALID_LOCATION: + throw new TimeObjects_Exception(_("Invalid location provided.")); + case SERVICES_WEATHER_ERROR_INVALID_PARTNER_ID: + throw new TimeObjects_Exception(_("Invalid partner id.")); + case SERVICES_WEATHER_ERROR_INVALID_PRODUCT_CODE: + throw new TimeObjects_Exception(_("Invalid product code.")); + case SERVICES_WEATHER_ERROR_INVALID_LICENSE_KEY: + throw new TimeObjects_Exception(_("Invalid license key.")); + default: + throw new TimeObjects_Exception($search->getMessage()); + } + } + if (is_array($search)) { + throw new TimeObjects_Exception(_(sprintf("Several locations possible with the paramter: ", $this->_params['location']))); + } + $forecast = $weatherDotCom->getForecast($search, $this->_params['days']); + if (is_a($forecast, 'PEAR_Error')) { + throw new TimeObjects_Exception($forecast->getMessage()); + } + + $now = new Horde_Date(time()); + $objects = array(); + foreach ($forecast['days'] as $which => $data) { + $day = new Horde_Date($now); + $day->mday += $which; + $day_end = new Horde_Date($day); + $day_end->mday++; + + // For day 0, the day portion isn't available after a certain time + // simplify and just check for it's presence or use night. + $title = sprintf("%s %d%s/%d%s", (!empty($data['day']['condition']) ? $data['day']['condition'] : $data['night']['condition']), + $data['temperatureHigh'], + $units['temp'], + $data['temperatureLow'], + $units['temp']); + $objects[] = array('id' => $day->timestamp(), //??? + 'title' => $title, + 'start' => sprintf('%d-%02d-%02dT00:00:00', + $day->year, + $day->month, + $day->mday), + 'end' => sprintf('%d-%02d-%02dT00:00:00', + $day_end->year, + $day_end->month, + $day_end->mday), + 'recurrence' => Horde_Date_Recurrence::RECUR_NONE, + 'params' => array(), + 'icon' => Horde::url($GLOBALS['registry']->getImageDir('horde') . '/block/weatherdotcom/23x23/' . ($data['day']['conditionIcon'] == '-' ? 'na' : $data['day']['conditionIcon']) . '.png', true, false) + ); + } + + return $objects; + } + +} \ No newline at end of file diff --git a/timeobjects/lib/Exception.php b/timeobjects/lib/Exception.php new file mode 100644 index 000000000..9aee528b8 --- /dev/null +++ b/timeobjects/lib/Exception.php @@ -0,0 +1,7 @@ + '{urn:horde}stringArray' +); + +$_services['listTimeObjects'] = array( + 'args' => array('categories' => '{urn:horde}stringArray', 'start' => 'int', 'end' => 'int'), + 'type' => '{urn:horde}hashHash' +); + +// @TODO: Probably implement a URL endpoint or something so we can link +// to the correct external site depending on what time object category +// we are referring to. +$_services['show'] = array( + 'link' => '#', +); + +/** + * Returns the available categories we provide. + * + * Right now, only providing weather data. + * + * @return array + */ +function _timeobjects_listTimeObjectCategories() +{ + return array('weather' => _("Weather")); +} + +/** + * Obtain the timeObjects for the requested category + * + * @param array $time_categories An array of categories to list + * @param mixed $start The start of the time period to list for + * @param mixed $end The end of the time period to list for + * + * @return An array of timeobject arrays. + */ +function _timeobjects_listTimeObjects($time_categories, $start, $end) +{ + require_once dirname(__FILE__) . '/base.php'; + + $return = array(); + foreach ($time_categories as $category) { + $drv = TimeObjects_Driver::factory($category); + $new = $drv->listTimeObjects($start, $end); + $return = array_merge($return, $new); + } + + return $return; +} \ No newline at end of file diff --git a/timeobjects/lib/base.php b/timeobjects/lib/base.php new file mode 100644 index 000000000..59a65f4a5 --- /dev/null +++ b/timeobjects/lib/base.php @@ -0,0 +1,44 @@ +pushApp('timeobjects', !defined('AUTH_HANDLER'))), 'PEAR_Error')) { + if ($pushed->getCode() == 'permission_denied') { + Horde::authenticationFailureRedirect(); + } + Horde::fatal($pushed, __FILE__, __LINE__, false); +} + +if (!defined('TIMEOBJECTS_BASE')) { + define('TIMEOBJECTS_BASE', $rto_dir . '/..'); +} \ No newline at end of file