Overview

Packages

  • Service
    • Weather

Classes

  • Horde_Service_Weather
  • Horde_Service_Weather_Base
  • Horde_Service_Weather_Current_Base
  • Horde_Service_Weather_Current_Google
  • Horde_Service_Weather_Current_WeatherUnderground
  • Horde_Service_Weather_Current_Wwo
  • Horde_Service_Weather_Exception
  • Horde_Service_Weather_Exception_InvalidProperty
  • Horde_Service_Weather_Forecast_Base
  • Horde_Service_Weather_Forecast_Google
  • Horde_Service_Weather_Forecast_WeatherUnderground
  • Horde_Service_Weather_Forecast_Wwo
  • Horde_Service_Weather_Google
  • Horde_Service_Weather_Period_Base
  • Horde_Service_Weather_Period_Google
  • Horde_Service_Weather_Period_WeatherUnderground
  • Horde_Service_Weather_Period_Wwo
  • Horde_Service_Weather_Station
  • Horde_Service_Weather_Translation
  • Horde_Service_Weather_WeatherUnderground
  • Horde_Service_Weather_Wwo
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * This file contains the Horde_Service_Weather class for communicating with
  4:  * the (unofficial) google weather API.
  5:  *
  6:  * Copyright 2011-2012 Horde LLC (http://www.horde.org/)
  7:  *
  8:  * @author   Michael J Rubinsky <mrubinsk@horde.org>
  9:  * @license  http://www.horde.org/licenses/bsd BSD
 10:  * @category Horde
 11:  * @package  Service_Weather
 12:  */
 13: 
 14: /**
 15:  * Horde_Service_Weather_Google.
 16:  *
 17:  * @author   Michael J Rubinsky <mrubinsk@horde.org>
 18:  * @category Horde
 19:  * @package  Service_Weather
 20:  */
 21: class Horde_Service_Weather_Google extends Horde_Service_Weather_Base
 22: {
 23:     const API_URL = 'http://www.google.com/ig/api';
 24: 
 25:     /**
 26:      * Language to request strings from Google in.
 27:      *
 28:      * @var string
 29:      */
 30:     protected $_language = 'en';
 31: 
 32:     /**
 33:      * Holds the units that Google actually returns the results in.
 34:      *
 35:      * Google returns forecast values in the units it sees as appropriate for
 36:      * the requested location.
 37:      *
 38:      * @var integer
 39:      */
 40:     public $internalUnits;
 41: 
 42:     public $title = 'Google Weather';
 43: 
 44:     public $link = 'http://google.com';
 45: 
 46:     /**
 47:      * Icon map for wunderground.
 48:      *
 49:      * Note some are returned as "sky" conditions and some as "condition"
 50:      * icons. Public so it can be overridded in client code if desired.
 51:      */
 52:     public $iconMap = array(
 53:         'chance_of_rain' => '11.png',
 54:         'chance_of_snow' => '14.png',
 55:         'chance_of_storm' => '3.png',
 56:         'chance_of_tstorm' => '3.png',
 57:         'clear' => '32.png',
 58:         'cloudy' => '26.png',
 59:         'flurries' => '14.png',
 60:         'fog' => '20.png',
 61:         'haze' => '21.png',
 62:         'mostly_cloudy' => '28.png',
 63:         'mostly_sunny' => '34.png',
 64:         'partly_cloudy' => '30.png',
 65:         'partlysunny' => '30.png',
 66:         'sleet' => '10.png',
 67:         'rain' => '12.png',
 68:         'snow' => '16.png',
 69:         'sunny' => '32.png',
 70:         'thunderstorm' => '3.png',
 71:         'storm' => '12.png',
 72:         'mist' => '29.png',
 73:         'icy' => '7.png',
 74:         'dust' => '19.png',
 75:         'smoke' => '22.png'
 76:     );
 77: 
 78:     /**
 79:      * Constructor.
 80:      *
 81:      * @param array $params  Parameters:
 82:      *                       - 'http_client': Required http client object
 83:      *                       - 'language': Language code for returned strings.
 84:      *
 85:      * @return Horde_Service_Weather_Base
 86:      */
 87:     public function __construct(array $params = array())
 88:     {
 89:         if (!empty($params['language'])) {
 90:             $this->_language = $params['language'];
 91:         }
 92: 
 93:         parent::__construct($params);
 94:     }
 95: 
 96:     /**
 97:      * Returns the current observations.
 98:      *
 99:      * @return Horde_Service_Weather_Current
100:      */
101:     public function getCurrentConditions($location)
102:     {
103:         $this->_getCommonElements($location);
104:         return $this->_current;
105:     }
106: 
107:     /**
108:      * Returns the forecast for the current location.
109:      *
110:      * @see Horde_Service_Weather_Base#getForecast
111:      */
112:     public function getForecast($location,
113:                                 $length = Horde_Service_Weather::FORECAST_3DAY,
114:                                 $type = Horde_Service_Weather::FORECAST_TYPE_STANDARD)
115:     {
116:         $this->_getCommonElements($location);
117:         return $this->_forecast;
118:     }
119: 
120:     /**
121:      * Searches for a valid location code.
122:      *
123:      * @param string $location  A location search string like e.g., Boston,MA.
124:      * @param integer $type     The type of search being performed.
125:      *
126:      * @return string  The search location suitable to use directly in a
127:      *                 weather request.
128:      */
129:     public function searchLocations($location,
130:                                     $type = Horde_Service_Weather::SEARCHTYPE_STANDARD)
131:     {
132:         // Google doesn't support any location searching via the weather api.
133:         // Just return the passed in value and hope for the best.
134:         if ($type == Horde_Service_Weather::SEARCHTYPE_IP) {
135:             throw new Horde_Service_Weather_Exception('Location by IP is not supported by this driver.');
136:         }
137: 
138:         $this->_getCommonElements($location);
139:         return $this->_station;
140:     }
141: 
142:     /**
143:      * Returns a list of supported forecast lengths.
144:      *
145:      * @return array The array of supported lengths.
146:      */
147:     public function getSupportedForecastLengths()
148:     {
149:         return array(3 => Horde_Service_Weather::FORECAST_3DAY);
150:     }
151: 
152:     /**
153:      */
154:     protected function _getCommonElements($location)
155:     {
156:         if (!empty($this->_current) && $location == $this->_lastLocation) {
157:             return;
158:         }
159: 
160:         $this->_lastLocation = $location;
161:         $url = new Horde_Url(self::API_URL);
162:         $url = $url->add(array(
163:             'weather' => $location,
164:             'hl' => $this->_language
165:         ))->setRaw(true);
166:         $results = $this->_makeRequest($url);
167:         if ($results->weather->problem_cause) {
168:             throw new Horde_Service_Weather_Exception(
169:                 Horde_Service_Weather_Translation::t("There was a problem with the weather request. Maybe an invalid location?"));
170:         }
171:         $this->internalUnits = $results->weather->forecast_information->unit_system['data'] == 'US' ?
172:                 Horde_Service_Weather::UNITS_STANDARD :
173:                 Horde_Service_Weather::UNITS_METRIC;
174: 
175:         $this->_station = $this->_parseStation($results->weather->forecast_information);
176: 
177:         // Sunrise/Sunset
178:         if (!empty($this->_station->lat)) {
179:             $date = new Horde_Date(time());
180:             $this->_station->sunset = new Horde_Date(date_sunset($date->timestamp(), SUNFUNCS_RET_TIMESTAMP, $this->_station->lat, $this->_station->lon));
181:             $this->_station->sunrise = new Horde_Date(date_sunrise($date->timestamp(), SUNFUNCS_RET_TIMESTAMP, $this->_station->lat, $this->_station->lon));
182:         }
183:         $this->_forecast = $this->_parseForecast($results->weather);
184:         $this->_current = $this->_parseCurrent($results->weather->current_conditions);
185:         $this->_current->time = new Horde_Date((string)$results->weather->forecast_information->current_date_time['data']);
186:     }
187: 
188:     /**
189:      * Parses the JSON response for a location request into a station object.
190:      *
191:      * @param object $station  The response from a Location request.
192:      *
193:      * @return Horde_Service_Weather_Station
194:      */
195:     protected function _parseStation($station)
196:     {
197:         $properties = array(
198:             // @TODO: can we parse cith/state from results?
199:             'name' => urldecode((string)$station->city['data']),
200:             'city' => urldecode((string)$station->city['data']),
201:             'state' => urldecode((string)$station->city['data']),
202:             'country' => '',
203:             'country_name' => '',
204:             'tz' => '', // Not provided, can we assume it's the location's local?
205:             'lat' => $station->latitude_e6['data'],
206:             'lon' => $station->longitude_e6['data'],
207:             'zip' => '',
208:             'code' => (string)$station->postal_code['data'],
209:             'time' => (string)$station->current_date_time['data']
210:         );
211: 
212:         return new Horde_Service_Weather_Station($properties);
213:     }
214: 
215:     /**
216:      * Parses the forecast data.
217:      *
218:      * @param object $forecast  The result of the forecast request.
219:      *
220:      * @return Horde_Service_Weather_Forecast_Google  The forecast.
221:      */
222:     protected function _parseForecast($forecast)
223:     {
224:         $forecast = new Horde_Service_Weather_Forecast_Google($forecast, $this);
225:         return $forecast;
226:     }
227: 
228:     /**
229:      * Parses the current_conditions response.
230:      *
231:      * @param object $current  The current_condition request response object.
232:      *
233:      * @return Horde_Service_Weather_Current_Google
234:      */
235:     protected function _parseCurrent($current)
236:     {
237:         // The Current object takes care of the parsing/mapping.
238:         $current = new Horde_Service_Weather_Current_Google($current, $this);
239:         $current->units = $this->units;
240: 
241:         return $current;
242:     }
243: 
244:     /**
245:      *
246:      * @return SimplexmlElement
247:      * @throws Horde_Service_Weather_Exception
248:      */
249:     protected function _makeRequest($url)
250:     {
251:         $cachekey = md5('hordeweather' . $url);
252:         if ((!empty($this->_cache) &&
253:              !($results = $this->_cache->get($cachekey, $this->_cache_lifetime))) ||
254:             empty($this->_cache)) {
255:             $response = $this->_http->get($url);
256:             if (!$response->code == '200') {
257:                 throw new Horde_Service_Weather_Exception($response->code);
258:             }
259:             $ct = $response->getHeader('content-type');
260:             $results = $response->getBody();
261:             $matches = array();
262:             if (preg_match("@charset=([^;\"'/>]+)@i", $ct, $matches)) {
263:                 $results = Horde_String::convertCharset($results, $matches[1], 'utf-8');
264:             }
265:             if (!empty($this->_cache)) {
266:                $this->_cache->set($cachekey, $results);
267:             }
268:         }
269:         try {
270:             return new SimplexmlElement($results);
271:         } catch (Exception $e) {
272:             throw new Horde_Service_Weather_Exception($e);
273:         }
274:     }
275: 
276: }
API documentation generated by ApiGen