Files
server/usr/share/psa-pear/pear/horde-service-weather-metar-database
2026-01-07 20:52:11 +01:00

283 lines
8.0 KiB
PHP

#!/usr/bin/env php
<?php
/**
* Script to create/recreate the metar database.
*
* For TCP connections:
* Usage: horde-service-weather-metar-database
* --adapter=pdo_mysql
* [--host=db.example.com]
* [--username=user]
* [--password=secret]
* [--database=db]
* [--debug]
*
* For Unix sockets:
*
* Usage: horde-service-weather-metar-database
* --adapter=pdo_mysql
* [--protocol=unix]
* [--socket=/path/to/mysql/mysqld.sock]
* [--username=user]
* [--password=secret]
* [--database=db]
* [--debug]
*
* Copyright 2016-2017 Horde LLC (http://www.horde.org/)
*
* See the enclosed file COPYING for license information (BSD). If you did
* not receive this file, see http://www.horde.org/licenses/bsd
*
* @author Michael J Rubinsky <mrubinsk@horde.org>
*/
require_once 'Horde/Autoloader/Default.php';
/**
* Ensure we can get the data file.
*
*/
function _checkForMetarData()
{
// First see if we have a local copy in the same directory.
$file_name = __DIR__ . DIRECTORY_SEPARATOR . 'airport-codes.csv';
$file_location = 'https://raw.githubusercontent.com/datasets/airport-codes/master/data/airport-codes.csv';
if (file_exists($file_name)) {
return file($file_name);
}
return file($file_location);
}
/**
* Drop the horde_metar_airports table.
*
*/
function _down($db)
{
$tableList = $db->tables();
if (in_array('horde_metar_airports', $tableList)) {
$db->dropTable('horde_metar_airports');
}
}
/**
* Create table
*
*/
function _createTable($db, $cli)
{
// Create table
try {
$t = $db->createTable('horde_metar_airports', array('autoincrementKey' => array('id')));
} catch (Horde_Db_Exception $e) {
$cli->fatal($e->getMessage());
}
$t->column('id', 'integer');
$t->column('icao', 'string', array('limit' => 4));
$t->column('name', 'string', array('limit' => 80));
$t->column('state', 'string', array('limit' => 4));
$t->column('country', 'string', array('limit' => 50));
$t->column('municipality', 'string', array('limit' => 80));
$t->column('latitude', 'float', array('default' => 0));
$t->column('longitude', 'float', array('default' => 0));
$t->column('elevation', 'float', array('default' => 0));
$t->end();
}
/**
* Parse metar data into database. Each row has the following fields:
*
* ident
* type
* name
* latitude_deg
* longitude_deg
* elevation_ft
* continent
* iso_country
* iso_region
* municipality
* gps_code
* iata_code
* local_code
*/
function _parse($db, $cli, $metar_rows)
{
// Parse data
$line = 0;
$insert = 'INSERT INTO horde_metar_airports '
. '(id, icao, name, state, country, municipality, latitude,'
. 'longitude, elevation) '
. 'VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?)';
// Using array_map('str_getcsv', file($file_location)) leads to memory
// exhaustion on my dev boxes, so iterate to be safe.
for ($i = 1; $i <= count($metar_rows) - 1; $i++) {
// Get csv fields.
$fields = str_getcsv(trim($metar_rows[$i]));
// Comment or some other broken row.
if (sizeof($fields) < 13) {
continue;
}
// Build param array
$data = array(
$line,
$fields[0],
$fields[2],
str_replace($fields[7] . '-', '', $fields[8]),
$fields[7],
$fields[9],
!empty($fields[3]) ? round($fields[3], 4) : 0,
!empty($fields[4]) ? round($fields[4], 4) : 0,
!empty($fields[5]) ? $fields[5] : 0
);
// Only add lines that have a valid ICAO identifier. The dataset
// seems to have a number of entries with broken identifiers. E.g.,
// Corydon airport.
if (strlen(trim($data[1])) > 4) {
continue;
}
// Insert
try {
$db->insert($insert, $data);
$line++;
} catch (Horde_Db_Exception $e) {
$cli->message('ERROR: ' . $e->getMessage(), 'cli.error');
$cli->message('SQL: ' . $insert . ' with the following data: ' . print_r($data, true), 'cli.error');
}
}
return $i;
}
// Init Cli
$cli = new Horde_Cli();
if (!$cli->runningFromCLI()) {
$cli->fatal('Must be run from the command line.');
}
$cli->init();
// Setup the Argv Parser.
$parser = new Horde_Argv_Parser(
array(
'usage' => "%prog\n\t--adapter=phptype\n\t[--host=db.example.com]\n\t[--socket=/path/to/mysqld.sock]\n\t[--username=username]\n\t[--password=secret]\n\t[--database=dbname]\n\t[--debug]",
'optionList' => array(
new Horde_Argv_Option('-a', '--adapter', array(
'action' => 'store',
'help' => 'Type of database adapter to use E.g., pdo_mysql',
'dest' => 'adapter'
)),
new Horde_Argv_Option('', '--host', array(
'action' => 'store',
'help' => 'Database host, if using TCP connections',
'dest' => 'host'
)),
new Horde_Argv_Option('-s', '--socket', array(
'action' => 'store',
'help' => 'Location of unix socket',
'dest' => 'socket'
)),
new Horde_Argv_Option('-u', '--username', array(
'action' => 'store',
'help' => 'Username to connect to database with',
'dest' => 'username'
)),
new Horde_Argv_Option('-p', '--password', array(
'action' => 'store',
'help' => 'Password',
'dest' => 'password'
)),
new Horde_Argv_Option('-d', '--database', array(
'action' => 'store',
'help' => 'Database name to connect to',
'dest' => 'database',
'default' => 'horde'
)),
new Horde_Argv_Option('', '--debug', array(
'action' => 'store_true',
'help' => 'Enable debug output from database',
'dest' => 'debug'
)),
)
)
);
list($params, $argv) = $parser->parseArgs();
// Sanity check parameters.
if (empty($params['adapter'])) {
$cli->message(
'The --adapter parameter is required.',
'cli.error'
);
$parser->printHelp();
exit;
}
if (empty($params['host']) && empty($params['socket'])) {
$cli->message(
'You must provide either a --host or --socket parameter.',
'cli.error'
);
$parser->printHelp();
exit;
}
// $params is a Horde_Argv_Values object, db object needs array.
$params = (array)$params;
if (!empty($params['socket'])) {
$params['protocol'] = 'unix';
unset($params['host']);
} else {
unset($params['socket']);
}
// Build Horde_Db adapter.
$class = 'Horde_Db_Adapter_' . str_replace(' ', '_', Horde_String::ucwords(str_replace('_', ' ', basename($params['adapter']))));
if (!class_exists($class)) {
$cli->fatal($params['adapter'] . 'is not a valid adapter name.');
}
unset($params['adapter']);
try {
$db = new $class($params);
} catch (Exception $e) {
$cli->fatal($e->getMessage());
}
// Setup any logging.
if (!empty($params['debug'])) {
$logger = new Horde_Log_Logger(new Horde_Log_Handler_Stream(STDOUT));
$db->setLogger($logger);
}
$logger = new Horde_Log_Logger(
new Horde_Log_Handler_Stream(
STDOUT,
null,
new Horde_Log_Formatter_Simple('%message%' . PHP_EOL)
)
);
// Start building.
$cli->message('Creating METAR database.', 'cli.message');
$metar_rows = _checkForMetarData();
if (empty($metar_rows)) {
$cli->message('Unable to locate METAR data.', 'cli.error');
exit;
}
// Drop any current data in case we are regenerating/updating.
_down($db);
// Create the table
_createTable($db, $cli);
// Parse data and add to datebase.
$cnt = _parse($db, $cli, $metar_rows);
// Done!
$cli->message(sprintf('Added %d airport identifiers to the database.', $cnt), 'cli.success');