Overview

Packages

  • Horde
  • None

Classes

  • Horde_Ajax_Application
  • Horde_Api
  • Horde_Block_Account
  • Horde_Block_Account_Base
  • Horde_Block_Account_Finger
  • Horde_Block_Account_Ldap
  • Horde_Block_Account_Localhost
  • Horde_Block_Cloud
  • Horde_Block_FbStream
  • Horde_Block_Feed
  • Horde_Block_Fortune
  • Horde_Block_Google
  • Horde_Block_Iframe
  • Horde_Block_Metar
  • Horde_Block_Moon
  • Horde_Block_Sunrise
  • Horde_Block_Time
  • Horde_Block_TwitterTimeline
  • Horde_Block_Vatid
  • Horde_Block_Weather
  • Horde_LoginTasks_SystemTask_GarbageCollection
  • Horde_LoginTasks_SystemTask_Upgrade
  • Horde_LoginTasks_Task_AdminCheck
  • Horde_LoginTasks_Task_LastLogin
  • Horde_LoginTasks_Task_TosAgreement
  • Horde_Prefs_Ui
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * Portal block for displaying weather information obtained via
  4:  * Horde_Service_Weather.
  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:  * @package Horde
 11:  */
 12: 
 13: /**
 14:  * Horde_Block_Weather
 15:  *
 16:  * @author   Michael J Rubinsky <mrubinsk@horde.org>
 17:  * @package  Horde
 18:  */
 19: class Horde_Block_Weather extends Horde_Core_Block
 20: {
 21:     /**
 22:      */
 23:     public $updateable = true;
 24: 
 25:     protected $_refreshParams;
 26: 
 27:     /**
 28:      */
 29:     public function __construct($app, $params = array())
 30:     {
 31:         // @TODO: Check config key etc...
 32:         parent::__construct($app, $params);
 33:         $this->_name = _("weather");
 34:     }
 35: 
 36:     /**
 37:      * Handle user initiated block refresh. Set a private member to avoid
 38:      * BC issues with having to add a parameter to the _content method.
 39:      *
 40:      * @param Horde_Variables $vars
 41:      *
 42:      * @return string
 43:      */
 44:     public function refreshContent($vars = null)
 45:     {
 46:         $this->_refreshParams = $vars;
 47:         return $this->_content();
 48:     }
 49: 
 50:     /**
 51:      */
 52:     protected function _title()
 53:     {
 54:         return _("Weather");
 55:     }
 56: 
 57:     /**
 58:      */
 59:     protected function _params()
 60:     {
 61:         $weather = $GLOBALS['injector']
 62:             ->getInstance('Horde_Weather');
 63:         $lengths = $weather->getSupportedForecastLengths();
 64:         return array(
 65:             'location' => array(
 66:                 'type' => 'text',
 67:                 'name' => _("Location"),
 68:                 'default' => 'Boston,MA'
 69:             ),
 70:             'units' => array(
 71:                 'type' => 'enum',
 72:                 'name' => _("Units"),
 73:                 'default' => 'standard',
 74:                 'values' => array(
 75:                     Horde_Service_Weather::UNITS_STANDARD => _("English"),
 76:                     Horde_Service_Weather::UNITS_METRIC =>  _("Metric")
 77:                 )
 78:             ),
 79:             'days' => array(
 80:                 'type' => 'enum',
 81:                 'name' => _("Forecast Days (note that the returned forecast returns both day and night; a large number here could result in a wide block)"),
 82:                 'default' => 3,
 83:                 'values' => $lengths
 84:             ),
 85:             'detailedForecast' => array(
 86:                 'type' => 'checkbox',
 87:                 'name' => _("Display detailed forecast"),
 88:                 'default' => 0
 89:             )
 90:         );
 91:     }
 92: 
 93:     /**
 94:      */
 95:     protected function _content()
 96:     {
 97:         global $conf, $prefs;
 98: 
 99:         $weather = $GLOBALS['injector']
100:             ->getInstance('Horde_Weather');
101: 
102:         // Set the requested units.
103:         $weather->units = $this->_params['units'];
104: 
105:         if (!empty($this->_refreshParams) && !empty($this->_refreshParams->location)) {
106:             $location = $this->_refreshParams->location;
107:             $html = '';
108:             $instance = '';
109:         } else {
110:             $instance = hash('md5', mt_rand());
111:             $GLOBALS['injector']
112:                 ->getInstance('Horde_Core_Factory_Imple')
113:                 ->create(
114:                     'WeatherLocationAutoCompleter',
115:                     array(
116:                         'triggerId' => 'location' . $instance,
117:                         'instance' => $instance
118:                     )
119:                 );
120: 
121:             $html = '<input id="location' . $instance . '" name="location' . $instance . '"><input type="button" id="button' . $instance . '" class="button" value="'
122:                 . _("Change Location") . '" /><span style="display:none;" id="location' . $instance . '_loading_img">'
123:                 . Horde::img('loading.gif') . '</span>';
124:             $location = $this->_params['location'];
125:         }
126: 
127:         // Test location
128:         try {
129:             $location = $weather->searchLocations($location);
130:         } catch (Horde_Service_Weather_Exception $e) {
131:             return $e->getMessage();
132:         }
133: 
134:         $html .= '<div id="weathercontent' . $instance . '">';
135: 
136:         if (is_array($location)) {
137:             // Several locations returned due to imprecise location parameter.
138:             $html = sprintf(_("Several locations possible with the parameter: %s"), $this->_params['location'])
139:                 . '<br />';
140:             foreach ($location as $real_location) {
141:                 $html .= '<li>' . $real_location->city . ', ' . $real_location->state . '(' . $real_location->code . ")</li>\n";
142:             }
143:             $html .= '</ul>';
144:             return $html;
145:         }
146:         try {
147:             $forecast = $weather->getForecast($location->code, $this->_params['days']);
148:             $station = $weather->getStation();
149:             $current = $weather->getCurrentConditions($location->code);
150:         } catch (Horde_Service_Weather_Exception $e) {
151:             return $e->getMessage();
152:         }
153: 
154:         // Units to display as
155:         $units = $weather->getUnits($weather->units);
156: 
157:         // Location and local time.
158:         $html .= '<div class="control">'
159:             . '<strong>' . $station->name . '</strong>';
160:         if ($current->time->timestamp()) {
161:             $html .= ' ' . sprintf(_("Local time: %s %s"), $current->time->strftime($GLOBALS['prefs']->getValue('date_format')), $current->time->strftime($GLOBALS['prefs']->getValue('time_format')));
162:         }
163:         $html .= '</div>';
164: 
165:         // Sunrise/sunset.
166:         if ($station->sunrise) {
167:             $html .= '<strong>' . _("Sunrise") . ': </strong>'
168:                 . Horde::img('block/sunrise/sunrise.png', _("Sunrise"))
169:                 . sprintf("%s %s", $station->sunrise->strftime($GLOBALS['prefs']->getValue('date_format')), $station->sunrise->strftime($GLOBALS['prefs']->getValue('time_format')));
170:             $html .= ' <strong>' . _("Sunset") . ': </strong>'
171:                 . Horde::img('block/sunrise/sunset.png', _("Sunset"))
172:                 . sprintf("%s %s", $station->sunset->strftime($GLOBALS['prefs']->getValue('date_format')), $station->sunset->strftime($GLOBALS['prefs']->getValue('time_format')));
173:             $html .= '<br />';
174:         }
175: 
176:         // Temperature.
177:         $html .= '<strong>' . _("Temperature") . ': </strong>' .
178:             $current->temp . '&deg;' . Horde_String::upper($units['temp']);
179: 
180:         // Dew point.
181:         if (is_numeric($current->dewpoint)) {
182:             $html .= ' <strong>' . _("Dew point") . ': </strong>' .
183:                     round($current->dewpoint) . '&deg;' . Horde_String::upper($units['temp']);
184:         }
185: 
186:         // Feels like temperature.
187:         // @TODO: Need to parse if wind chill/heat index etc..
188:         // $html .= ' <strong>' . _("Feels like: ") . '</strong>' .
189:         //     round($weather['feltTemperature']) . '&deg;' . Horde_String::upper($units['temp']);
190: 
191:         // Pressure and trend.
192:         if ($current->pressure) {
193:             $html .= '<br /><strong>' . _("Pressure") . ': </strong>';
194:             $trend = $current->pressure_trend;
195:             if (empty($trend)) {
196:                 $html .= sprintf('%d %s',
197:                                  round($current->pressure), $units['pres']);
198:             } else {
199:                 $html .= sprintf(_("%d %s and %s"),
200:                                  round($current->pressure), $units['pres'],
201:                                  _($trend));
202:             }
203:         }
204:         if ($current->wind_direction) {
205:             // Wind.
206:             $html .= '<br /><strong>' . _("Wind") . ': </strong>';
207: 
208:             $html .= sprintf(
209:                 _("From the %s (%s &deg;) at %s %s"),
210:                 $current->wind_direction,
211:                 $current->wind_degrees,
212:                 $current->wind_speed,
213:                 $units['wind']);
214:             if ($current->wind_gust > 0) {
215:                 $html .= ', ' . _("gusting") . ' ' . $current->wind_gust . ' ' . $units['wind'];
216:             }
217:         }
218: 
219:         // Humidity.
220:         if ($current->humidity) {
221:             $html .= '<br /><strong>' . _("Humidity") . ': </strong>' . $current->humidity;
222:         }
223: 
224:         if ($current->visibility) {
225:             // Visibility.
226:             $html .= ' <strong>' . _("Visibility") . ': </strong>'
227:                 . round($current->visibility) . ' ' . $units['vis'];
228:         }
229: 
230:         // Current condition.
231:         $condition = $current->condition;
232:         $html .= '<br /><strong>' . _("Current condition") . ': </strong>'
233:             . Horde::img(Horde_Themes::img('weather/32x32/' . $current->icon))
234:             .  ' ' . $condition;
235: 
236:         // Forecast
237:         if ($this->_params['days'] > 0) {
238:             $html .= '<div class="control"><strong>' .
239:                 sprintf(_("%d-day forecast"), $this->_params['days']) .
240:                 '</strong></div>';
241: 
242:             $futureDays = 0;
243:             $html .= '<table class="horde-block-weather">';
244: 
245:             // Headers.
246:             $html .= '<tr>';
247:             $html .= '<th>' . _("Day") . '</th><th>' .
248:             sprintf(_("Temperature%s(%sHi%s/%sLo%s)"),
249:                         '<br />',
250:                         '<span style="color:red">', '</span>',
251:                         '<span style="color:blue">', '</span>') .
252:                 '</th><th>' . _("Condition") . '</th>';
253: 
254:             if (isset($this->_params['detailedForecast'])) {
255:                 if (in_array(Horde_Service_Weather::FORECAST_FIELD_PRECIPITATION, $forecast->fields)) {
256:                     $html .= '<th>' . sprintf(_("Precipitation%schance"), '<br />') . '</th>';
257:                 }
258: 
259:                 if (in_array(Horde_Service_Weather::FORECAST_FIELD_HUMIDITY, $forecast->fields)) {
260:                     $html .= '<th>' . _("Humidity") . '</th>';
261:                 }
262: 
263:                 if (in_array(Horde_Service_Weather::FORECAST_FIELD_WIND, $forecast->fields)) {
264:                     $html .= '<th>' . _("Wind") . '</th>';
265:                 }
266:             }
267: 
268:             $html .= '</tr>';
269:             $which = -1;
270:             foreach ($forecast as $day) {
271:                  $which++;
272:                  if ($which > $this->_params['days']) {
273:                      break;
274:                  }
275:                  $html .= '<tr class="item0">';
276:                  // Day name.
277:                  $html .= '<td><strong>';
278: 
279:                  if ($which == 0) {
280:                      $html .= _("Today");
281:                  } elseif ($which == 1) {
282:                      $html .= _("Tomorrow");
283:                  } else {
284:                      $html .= strftime('%A', mktime(0, 0, 0, date('m'), date('d') + $futureDays, date('Y')));
285:                  }
286:                 $html .= '</strong><br />' .
287:                     strftime('%b %d', mktime(0, 0, 0, date('m'), date('d') + $futureDays, date('Y'))) .
288:                     '</td>';
289: 
290:                 // Forecast condition.
291:                 $condition = $day->conditions;
292: 
293:                 // Temperature.
294:                 $html .= '<td>'
295:                     . '<span style="color:red">' . $day->high . '&deg;'
296:                     . Horde_String::upper($units['temp']) . '</span>/'
297:                     . '<span style="color:blue">' . $day->low . '&deg;'
298:                     . Horde_String::upper($units['temp']) . '</span></td>';
299: 
300:                 // Condition.
301:                 $html .= '<td>'
302:                     . Horde::img(Horde_Themes::img('weather/32x32/' . $day->icon))
303:                     . '<br />' . $condition . '</td>';
304: 
305:                 if (isset($this->_params['detailedForecast'])) {
306:                     if (in_array(Horde_Service_Weather::FORECAST_FIELD_PRECIPITATION, $forecast->fields)) {
307:                         $html .= '<td>'
308:                             . ($day->precipitation_percent >= 0 ? $day->precipitation_percent . '%' : _("N/A")) . '</td>';
309:                     }
310:                     if (in_array(Horde_Service_Weather::FORECAST_FIELD_HUMIDITY, $forecast->fields)) {
311:                         $html .= '<td>'
312:                             . ($day->humidity ? $day->humidity . '%': _("N/A")) . '</td>';
313:                     }
314:                     if (in_array(Horde_Service_Weather::FORECAST_FIELD_WIND, $forecast->fields)) {
315:                         // Winds.
316:                         if ($day->wind_direction) {
317:                             $html .= '<td>' . ' '
318:                                 . sprintf(_("From the %s at %s %s"),
319:                                           $day->wind_direction,
320:                                           $day->wind_speed,
321:                                           $units['wind']);
322:                             if ($day->wind_gust && $day->wind_gust > $day->wind_speed) {
323:                                 $html .= ', ' . _("gusting") . ' '
324:                                     . $day->wind_gust . ' ' . $units['wind'];
325:                             }
326:                             $html .= '</td>';
327:                         } else {
328:                             $html .= '<td>' . _("N/A") . '</td>';
329:                         }
330:                     }
331:                 }
332:                 $html .= '</tr>';
333:                 $futureDays++;
334:             }
335:             $html .= '</table>';
336:         }
337: 
338:         if ($weather->logo) {
339:             $html .= '<div class="rightAlign">'
340:                 . _("Weather data provided by") . ' '
341:                 . Horde::link(
342:                     Horde::externalUrl($weather->link),
343:                     $weather->title, '', '_blank', '', $weather->title)
344:                 . Horde::img(new Horde_Themes_Image($weather->logo))
345:                 . '</a></div>';
346:         } else {
347:             $html .= '<div class="rightAlign">'
348:                 . _("Weather data provided by") . ' '
349:                 . Horde::link(
350:                     Horde::externalUrl($weather->link),
351:                     $weather->title, '', '_blank', '', $weather->title)
352:                 . '<em>' . $weather->title . '</em>'
353:                 . '</a></div>';
354:         }
355: 
356:         return $html . '</div>';
357:     }
358: 
359: }
360: 
API documentation generated by ApiGen