/horde-3.3.13/lib/Block/metar.php
PHP | 476 lines | 397 code | 46 blank | 33 comment | 76 complexity | 4bf13dd71e6ff629a3bcdf60ce6ac634 MD5 | raw file
1<?php 2 3if ((@include_once 'Services/Weather.php') && 4 !empty($GLOBALS['conf']['sql']['phptype'])) { 5 $block_name = _("Metar Weather"); 6} 7 8/** 9 * The Horde_Block_metar class provides an applet for the portal 10 * screen to display METAR weather data for a specified location 11 * (currently airports). 12 * 13 * $Horde: horde/lib/Block/metar.php,v 1.22.10.11 2009/01/16 17:05:59 mrubinsk Exp $ 14 * 15 * @package Horde_Block 16 */ 17class Horde_Block_Horde_metar extends Horde_Block { 18 19 /** 20 * Whether this block has changing content. 21 */ 22 var $updateable = true; 23 24 var $_app = 'horde'; 25 26 /** 27 * The title to go in this block. 28 * 29 * @return string The title text. 30 */ 31 function _title() 32 { 33 return _("Current Weather"); 34 } 35 36 function _params() 37 { 38 if (!@include_once 'Services/Weather.php') { 39 Horde::logMessage('The metar block will not work without Services_Weather from PEAR. Run pear install Services_Weather.', 40 __FILE__, __LINE__, PEAR_LOG_ERR); 41 return array( 42 'error' => array( 43 'type' => 'error', 44 'name' => _("Error"), 45 'default' => _("Metar block not available.") 46 ) 47 ); 48 } else { 49 global $conf; 50 51 // Get locations from the database. 52 require_once 'DB.php'; 53 $db = &DB::connect($conf['sql']); 54 if (is_a($db, 'PEAR_Error')) { 55 return $db; 56 } 57 58 // Set DB portability options. 59 switch ($db->phptype) { 60 case 'mssql': 61 $db->setOption('portability', DB_PORTABILITY_LOWERCASE | DB_PORTABILITY_ERRORS | DB_PORTABILITY_RTRIM); 62 break; 63 default: 64 $db->setOption('portability', DB_PORTABILITY_LOWERCASE | DB_PORTABILITY_ERRORS); 65 } 66 67 $result = $db->query('SELECT icao, name, country FROM metarAirports ORDER BY country'); 68 if (is_a($result, 'PEAR_Error')) { 69 return $result; 70 } 71 72 $locations = array(); 73 while ($row = $result->fetchRow(DB_FETCHMODE_ASSOC)) { 74 $locations[$row['country']][$row['icao']] = $row['name']; 75 } 76 77 return array( 78 'location' => array( 79 'type' => 'mlenum', 80 'name' => _("Location"), 81 'default' => 'KSFB', 82 'values' => $locations, 83 ), 84 'units' => array( 85 'type' => 'enum', 86 'name' => _("Units"), 87 'default' => 's', 88 'values' => array( 89 's' => _("Standard"), 90 'm' => _("Metric") 91 ) 92 ), 93 'knots' => array( 94 'type' => 'checkbox', 95 'name' => _("Wind speed in knots"), 96 'default' => 0 97 ), 98 'taf' => array( 99 'type' => 'checkbox', 100 'name' => _("Display forecast (TAF)"), 101 'default' => 0 102 ) 103 ); 104 } 105 } 106 107 function _row($label, $content) 108 { 109 return '<br /><strong>' . $label . ':</strong> ' . $content; 110 } 111 112 function _sameRow($label, $content) 113 { 114 return ' <strong>' . $label . ':</strong> ' . $content; 115 } 116 117 /** 118 * The content to go in this block. 119 * 120 * @return string The content 121 */ 122 function _content() 123 { 124 if (!@include_once 'Services/Weather.php') { 125 Horde::logMessage('The metar block will not work without Services_Weather from PEAR. Run pear install Services_Weather.', 126 __FILE__, __LINE__, PEAR_LOG_ERR); 127 return _("Metar block not available. Details have been logged for the administrator."); 128 } 129 130 global $conf; 131 static $metarLocs; 132 133 if (!isset($conf['sql'])) { 134 return _("A database backend is required for this block."); 135 } 136 137 if (empty($this->_params['location'])) { 138 return _("No location is set."); 139 } 140 141 if (!is_array($metarLocs)) { 142 $metarLocs = $this->getParams(); 143 } 144 145 $metar = &Services_Weather::service('METAR', array('debug' => 0)); 146 $metar->setMetarDB($conf['sql']); 147 $metar->setUnitsFormat($this->_params['units']); 148 $metar->setDateTimeFormat('M j, Y', 'H:i'); 149 $metar->setMetarSource('http'); 150 151 $units = $metar->getUnitsFormat($this->_params['units']); 152 $weather = $metar->getWeather($this->_params['location']); 153 if (is_a($weather, 'PEAR_Error')) { 154 $html = $weather->getMessage(); 155 return $html; 156 } 157 $html = '<table width="100%" cellspacing="0">' . 158 '<tr><td class="control"><strong>' . 159 sprintf('%s, %s (%s)', 160 $metarLocs['location']['values'][$this->_params['__location']][$this->_params['location']], 161 $this->_params['__location'], 162 $this->_params['location']) . 163 '</strong></td></tr></table><strong>' . _("Last Updated:") . '</strong> ' . 164 $weather['update'] . '<br /><br />'; 165 166 // Wind. 167 if (isset($weather['wind'])) { 168 $html .= '<strong>' . _("Wind:") . '</strong> '; 169 if ($weather['windDirection'] == 'Variable') { 170 if (!empty($this->_params['knots'])) { 171 $html .= sprintf(_("%s at %s %s"), 172 $weather['windDirection'], 173 round($metar->convertSpeed($weather['wind'], 174 $units['wind'], 'kt')), 175 'kt'); 176 } else { 177 $html .= sprintf(_("%s at %s %s"), 178 $weather['windDirection'], 179 round($weather['wind']), 180 $units['wind']); 181 } 182 } elseif (($weather['windDegrees'] == '000') && 183 ($weather['wind'] == '0')) { 184 $html .= sprintf(_("calm")); 185 } else { 186 $html .= sprintf(_("from the %s (%s) at %s %s"), 187 $weather['windDirection'], 188 $weather['windDegrees'], 189 empty($this->_params['knots']) ? 190 round($weather['wind']) : 191 round($metar->convertSpeed($weather['wind'], $units['wind'], 'kt')), 192 empty($this->_params['knots']) ? 193 $units['wind'] : 194 'kt'); 195 } 196 } 197 if (isset($weather['windGust'])) { 198 if ($weather['windGust']) { 199 if (!empty($this->_params['knots'])) { 200 $html .= sprintf(_(", gusting %s %s"), 201 round($metar->convertSpeed($weather['windGust'], 202 $units['wind'], 'kt')), 203 'kt'); 204 } else { 205 $html .= sprintf(_(", gusting %s %s"), 206 round($weather['windGust']), 207 $units['wind']); 208 } 209 } 210 } 211 if (isset($weather['windVariability'])) { 212 if ($weather['windVariability']['from']) { 213 $html .= sprintf(_(", variable from %s to %s"), 214 $weather['windVariability']['from'], 215 $weather['windVariability']['to']); 216 } 217 } 218 219 // Visibility. 220 if (isset($weather['visibility'])) { 221 $html .= $this->_sameRow(_("Visibility"), $weather['visibility'] . ' ' . $units['vis']); 222 } 223 224 // Temperature/DewPoint. 225 if (isset($weather['temperature'])) { 226 $html .= $this->_row(_("Temperature"), round($weather['temperature']) . '°' . String::upper($units['temp'])); 227 } 228 if (isset($weather['dewPoint'])) { 229 $html .= $this->_sameRow(_("Dew Point"), round($weather['dewPoint']) . '°' . String::upper($units['temp'])); 230 } 231 if (isset($weather['feltTemperature'])) { 232 $html .= $this->_sameRow(_("Feels Like"), round($weather['feltTemperature']) . '°' . String::upper($units['temp'])); 233 } 234 235 // Pressure. 236 if (isset($weather['pressure'])) { 237 $html .= $this->_row(_("Pressure"), $weather['pressure'] . ' ' . $units['pres']); 238 } 239 240 // Humidity. 241 if (isset($weather['humidity'])) { 242 $html .= $this->_sameRow(_("Humidity"), round($weather['humidity']) . '%'); 243 } 244 245 // Clouds. 246 if (isset($weather['clouds'])) { 247 $clouds = ''; 248 foreach ($weather['clouds'] as $cloud) { 249 $clouds .= '<br />'; 250 if (isset($cloud['height'])) { 251 $clouds .= sprintf(_("%s at %s %s"), $cloud['amount'], $cloud['height'], $units['height']); 252 } else { 253 $clouds .= $cloud['amount']; 254 } 255 } 256 $html .= $this->_row(_("Clouds"), $clouds); 257 } 258 259 // Conditions. 260 if (isset($weather['condition'])) { 261 $html .= $this->_row(_("Conditions"), $weather['condition']); 262 } 263 264 // Remarks. 265 if (isset($weather['remark'])) { 266 $remarks = ''; 267 $other = ''; 268 foreach ($weather['remark'] as $remark => $value) { 269 switch ($remark) { 270 case 'seapressure': 271 $remarks .= '<br />' . _("Pressure at sea level: ") . $value . ' ' . $units['pres']; 272 break; 273 274 case 'precipitation': 275 foreach ($value as $precip) { 276 if (is_numeric($precip['amount'])) { 277 $remarks .= '<br />' . 278 sprintf(ngettext("Precipitation for last %d hour: ", "Precipitation for last %d hours: ", $precip['hours']), 279 $precip['hours']) . 280 $precip['amount'] . ' ' . $units['rain']; 281 } else { 282 $remarks .= '<br />' . 283 sprintf(ngettext("Precipitation for last %d hour: ", "Precipitation for last %d hours: ", $precip['hours']), 284 $precip['hours']) . $precip['amount']; 285 } 286 } 287 break; 288 289 case 'snowdepth': 290 $remarks .= '<br />' . _("Snow depth: ") . $value . ' ' . $units['rain']; 291 break; 292 293 case 'snowequiv': 294 $remarks .= '<br />' . _("Snow equivalent in water: ") . $value . ' ' . $units['rain']; 295 break; 296 297 case 'sunduration': 298 $remarks .= '<br />' . sprintf(_("%d minutes"), $value); 299 break; 300 301 case '1htemp': 302 $remarks .= '<br />' . _("Temp for last hour: ") . round($value) . '°' . String::upper($units['temp']); 303 break; 304 305 case '1hdew': 306 $remarks .= '<br />' . _("Dew Point for last hour: ") . round($value) . '°' . String::upper($units['temp']); 307 break; 308 309 case '6hmaxtemp': 310 $remarks .= '<br />' . _("Max temp last 6 hours: ") . round($value) . '°' . String::upper($units['temp']); 311 break; 312 313 case '6hmintemp': 314 $remarks .= '<br />' . _("Min temp last 6 hours: ") . round($value) . '°' . String::upper($units['temp']); 315 break; 316 317 case '24hmaxtemp': 318 $remarks .= '<br />' . _("Max temp last 24 hours: ") . round($value) . '°' . String::upper($units['temp']); 319 break; 320 321 case '24hmintemp': 322 $remarks .= '<br />' . _("Min temp last 24 hours: ") . round($value) . '°' . String::upper($units['temp']); 323 break; 324 325 case 'sensors': 326 foreach ($value as $sensor) { 327 $remarks .= '<br />' . 328 _("Sensor: ") . $sensor; 329 } 330 break; 331 332 default: 333 $other .= '<br />' . $value; 334 break; 335 } 336 } 337 338 $html .= $this->_row(_("Remarks"), $remarks . $other); 339 } 340 341 // TAF 342 if (!empty($this->_params['taf'])) { 343 $taf = $metar->getForecast($this->_params['location']); 344 if (!is_a($taf, 'PEAR_Error')) { 345 $forecast = '<table width="100%" cellspacing="0">'; 346 $forecast .= '<tr><td class="control" colspan="2"><center><strong>' . _("Forecast (TAF)") . '</strong></td></tr></table>'; 347 $forecast .= '<strong>Valid: </strong>' . $taf['validFrom'] . ' - ' . $taf['validTo'] . '<br /><br />'; 348 $item = 0; 349 foreach ($taf['time'] as $time => $entry) { 350 $item++; 351 $forecast .= '<table width="100%" cellspacing="0">'; 352 $forecast .= '<tr class="item' . ($item % 2) . '">'; 353 $forecast .= '<td align="center" width="50">' . $time . '</td><td><strong>Wind:</strong> '; 354 if (isset($entry['wind'])) { 355 if ($entry['windDirection'] == 'Variable') { 356 if (!empty($this->_params['knots'])) { 357 $forecast .= sprintf(_("%s at %s %s"), 358 strtolower($entry['windDirection']), 359 round($metar->convertSpeed($entry['wind'], 360 $units['wind'], 'kt')), 361 'kt'); 362 } else { 363 $forecast .= sprintf(_("%s at %s %s"), 364 $entry['windDirection'], 365 round($entry['wind']), 366 $units['wind']); 367 } 368 } elseif (($entry['windDegrees'] == '000') && 369 ($entry['wind'] == '0')) { 370 $forecast .= sprintf(_("calm")); 371 } else { 372 $forecast .= sprintf(_("from the %s (%s) at %s %s"), 373 $entry['windDirection'], 374 $entry['windDegrees'], 375 empty($this->_params['knots']) ? 376 round($entry['wind']) : 377 round($metar->convertSpeed($entry['wind'], $units['wind'], 'kt')), 378 empty($this->_params['knots']) ? 379 $units['wind'] : 380 'kt'); 381 } 382 $forecast .= '<br />'; 383 } 384 if (isset($entry['temperatureLow']) || isset($entry['temperatureHigh'])) { 385 $forecast .= '<strong>Temperature</strong>'; 386 if (isset($entry['temperatureLow'])) { 387 $forecast .= '<strong> Low:</strong>'; 388 $forecast .= $entry['temperatureLow']; 389 } 390 if (isset($entry['temperatureHigh'])) { 391 $forecast .= '<strong> High:</strong>'; 392 $forecast .= $entry['temperatureHigh']; 393 } 394 $forecast .= '<br />'; 395 } 396 if (isset($entry['windshear'])) { 397 $forecast .= '<strong>Windshear:</strong>'; 398 $forecast .= sprintf(_("from the %s (%s) at %s %s"), 399 $entry['windshearDirection'], 400 $entry['windshearDegrees'], 401 $entry['windshearHeight'], 402 $units['height']); 403 $forecast .= '<br />'; 404 } 405 if (isset($entry['visibility'])) { 406 $forecast .= '<strong>Visibility:</strong> '; 407 $forecast .= strtolower($entry['visQualifier']) . ' ' . $entry['visibility'] . ' ' . $units['vis']; 408 $forecast .= '<br />'; 409 } 410 if (isset($entry['condition'])) { 411 $forecast .= '<strong>Conditions:</strong> '; 412 $forecast .= $entry['condition']; 413 $forecast .= '<br />'; 414 } 415 $forecast .= '<strong>Clouds:</strong> '; 416 foreach ($entry['clouds'] as $clouds) { 417 if (isset($clouds['type'])) { 418 $forecast .= ' ' . $clouds['type']; 419 } 420 $forecast .= ' ' . $clouds['amount']; 421 if (isset($clouds['height'])) { 422 $forecast .= ' at ' . $clouds['height'] . ' ' . $units['height']; 423 } else { 424 $forecast .= ' '; 425 } 426 } 427 $forecast .= '</td></tr>'; 428 if (isset($entry['fmc'])) { 429 $item++; 430 foreach ($entry['fmc'] as $fmcEntry) { 431 $forecast .= '<tr class="item' . ($item % 2) . '">'; 432 $forecast .= '<td align="center" width="50">'; 433 $forecast .= '* ' . $fmcEntry['from'] . '<br /> - ' . $fmcEntry['to'] . '</td>'; 434 $forecast .= '<td>'; 435 $forecast .= '<strong>Type: </strong>' . $fmcEntry['type']; 436 if (isset($fmcEntry['probability'])) { 437 $forecast .= ' <strong> Prob: </strong>' . $fmcEntry['probability'] . '%'; 438 } 439 if (isset($fmcEntry['condition'])) { 440 $forecast .= ' <strong> Conditions: </strong>' . $fmcEntry['condition']; 441 } 442 if (isset($fmcEntry['clouds'])) { 443 $forecast .= ' <strong>Clouds:</strong>'; 444 foreach ($fmcEntry['clouds'] as $fmcClouds) { 445 if (isset($fmcClouds['type'])) { 446 $forecast .= ' ' . $fmcClouds['type']; 447 } 448 if (isset($fmcClouds['height'])) { 449 $forecast .= ' ' . $fmcClouds['amount']; 450 $forecast .= ' ' . $fmcClouds['height']; 451 $forecast .= ' ' . $units['height']; 452 } else { 453 $forecast .= ' ' . $fmcClouds['amount']; 454 } 455 } 456 } 457 if (isset($fmcEntry['visQualifier'])) { 458 $forecast .= ' <strong>Visibility:</strong> '; 459 $forecast .= strtolower($fmcEntry['visQualifier']) . ' '; 460 $forecast .= $fmcEntry['visibility'] . ' ' . $units['vis']; 461 } 462 $forecast .= '</td></tr>'; 463 } 464 } 465 466 } 467 $forecast .= '</table>'; 468 469 $html .= $forecast; 470 } 471 } 472 473 return $html; 474 } 475 476}