PageRenderTime 47ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/horde-3.3.13/lib/Block/metar.php

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