PageRenderTime 45ms CodeModel.GetById 20ms app.highlight 20ms RepoModel.GetById 1ms app.codeStats 1ms

/lib/Block/metar.php

https://github.com/wrobel/horde-fw3
PHP | 476 lines | 397 code | 46 blank | 33 comment | 76 complexity | ca518da26b10f0c23d3989124ef94cfe 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']) . '&deg;' . String::upper($units['temp']));
227        }
228        if (isset($weather['dewPoint'])) {
229            $html .= $this->_sameRow(_("Dew Point"), round($weather['dewPoint']) . '&deg;' . String::upper($units['temp']));
230        }
231        if (isset($weather['feltTemperature'])) {
232            $html .= $this->_sameRow(_("Feels Like"), round($weather['feltTemperature']) . '&deg;' . 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) . '&deg;' . String::upper($units['temp']);
303                    break;
304
305                case '1hdew':
306                    $remarks .= '<br />' . _("Dew Point for last hour: ") . round($value) . '&deg;' . String::upper($units['temp']);
307                    break;
308
309                case '6hmaxtemp':
310                    $remarks .= '<br />' . _("Max temp last 6 hours: ") . round($value) . '&deg;' . String::upper($units['temp']);
311                    break;
312
313                case '6hmintemp':
314                    $remarks .= '<br />' . _("Min temp last 6 hours: ") . round($value) . '&deg;' . String::upper($units['temp']);
315                    break;
316
317                case '24hmaxtemp':
318                    $remarks .= '<br />' . _("Max temp last 24 hours: ") . round($value) . '&deg;' . String::upper($units['temp']);
319                    break;
320
321                case '24hmintemp':
322                    $remarks .= '<br />' . _("Min temp last 24 hours: ") . round($value) . '&deg;' . 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}