283 lines
8.0 KiB
PHP
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');
|