diff --git a/app/Console/Commands/Importer.php b/app/Console/Commands/Importer.php new file mode 100644 index 00000000..91ff255b --- /dev/null +++ b/app/Console/Commands/Importer.php @@ -0,0 +1,28 @@ + $this->argument('db_host'), + 'name' => $this->argument('db_name'), + 'user' => $this->argument('db_user'), + 'pass' => $this->argument('db_pass') + ]; + + $importerSvc = new \App\Console\Services\Importer($db_creds); + $importerSvc->run(); + } +} diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index f0584fe6..a515af9d 100755 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -17,6 +17,7 @@ class Kernel extends ConsoleKernel Commands\CreateDatabase::class, Commands\DevCommands::class, Commands\ImportCommand::class, + Commands\Importer::class, Commands\Install::class, Commands\NavdataCommand::class, Commands\TestApi::class, diff --git a/app/Console/Services/Importer.php b/app/Console/Services/Importer.php new file mode 100644 index 00000000..ddb28a11 --- /dev/null +++ b/app/Console/Services/Importer.php @@ -0,0 +1,405 @@ +log = new ConsoleOutput(); + + # The db credentials + $this->creds = array_merge([ + 'host' => 'localhost', + 'port' => 3306, + 'name' => '', + 'user' => '', + 'pass' => '', + ], $db_creds); + } + + /** + * @return int|void + */ + public function run() + { + $this->reconnect(); + + # Import all the different parts + $this->importRanks(); + $this->importAirlines(); + $this->importAircraft(); + $this->importAirports(); + + $this->importUsers(); + $this->importFlights(); + $this->importPireps(); + + # Finish up + $this->recalculateRanks(); + } + + /** + * Reconnect to the old phpVMS DB using PDO + */ + protected function reconnect() + { + $dsn = 'mysql:' . implode(';', [ + 'host=' . $this->creds['host'], + 'port=' . $this->creds['port'], + 'dbname=' . $this->creds['name'] + ]); + + $this->info('Connection string: ' . $dsn); + + try { + $this->conn = new PDO($dsn, $this->creds['user'], $this->creds['pass']); + $this->conn->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ); + } catch (\PDOException $e) { + $this->error($e); + exit(); + } + } + + /** + * @param $message + */ + protected function comment($message) + { + $this->log->writeln('' . $message . ''); + } + + /** + * @param $message + */ + protected function error($message) { + $this->log->writeln('' . $message . ''); + } + + /** + * @param string $message + */ + protected function info($message) + { + if(\is_array($message)) { + print_r($message); + } + else { + $this->log->writeln(''.$message.''); + } + } + + /** + * Return the table name with the prefix + * @param $table + * @return string + */ + protected function tableName($table) + { + return 'phpvms_'.$table; + } + + /** + * + * @param \Illuminate\Database\Eloquent\Model $model + * @return bool + */ + protected function saveModel($model) + { + try { + $model->save(); + return true; + } catch (QueryException $e) { + #$this->error($e->getMessage()); + return false; + } + } + + /** + * @param $table + * @return mixed + */ + protected function getTotalRows($table) + { + $table = $this->tableName($table); + + $sql = 'SELECT COUNT(*) FROM ' . $table; + $rows = $this->conn->query($sql)->fetchColumn(); + + $this->info('Found '.$rows.' rows in '.$table); + return $rows; + } + + /** + * Read all the rows in a table, but read them in a batched manner + * @param string $table The name of the table + * @return \Generator + */ + protected function readRows($table) + { + $offset = 0; + $total_rows = $this->getTotalRows($table); + + while($offset < $total_rows) + { + $rows_to_read = $offset+self::BATCH_READ_ROWS; + if($rows_to_read > $total_rows) { + $rows_to_read = $total_rows; + } + + $this->info('Reading '.$offset.' to '.$rows_to_read.' of '.$total_rows); + + $sql = 'SELECT * FROM ' . $this->tableName($table) + . ' LIMIT ' . self::BATCH_READ_ROWS . ' OFFSET ' . $offset; + + try { + foreach ($this->conn->query($sql) as $row) { + yield $row; + } + } catch(PDOException $e) { + // Without incrementing the offset, it should re-run the same query + $this->error($e); + + if(strpos($e->getMessage(), 'server has gone away') !== false) { + $this->reconnect(); + continue; + } + } + + $offset += self::BATCH_READ_ROWS; + } + } + + /** + * + * All the individual importers, done on a per-table basis + * Some tables get saved locally for tables that use FK refs + * + */ + + /** + * Import all of the ranks + */ + protected function importRanks() + { + $this->comment('--- RANK IMPORT ---'); + + $count = 0; + foreach ($this->readRows('ranks') as $row) + { + $this->ranks[$row->rankid] = $row; + $this->ranks[$row->rank] = $row; + + $attrs = [ + 'name' => $row->rank, + 'link' => $row->rankimage, + 'hours' => $row->minhours, + ]; + + if($this->saveModel(new Rank($attrs))) { + ++$count; + } + } + + $this->info('Imported ' . $count . ' ranks'); + } + + /** + * Import all of the airlines. Save them all in the private var $airlines + * They're used to lookup from other reference tables + */ + protected function importAirlines() + { + $this->comment('--- AIRLINE IMPORT ---'); + + $count = 0; + foreach ($this->readRows('airlines') as $row) + { + $this->airlines[$row->id] = $row; + $this->airlines[$row->code] = $row; + + $attrs = [ + 'icao' => $row->code, + 'iata' => $row->code, + 'name' => $row->name, + 'active' => $row->enabled, + ]; + + if($this->saveModel(new Airline($attrs))) { + ++$count; + } + } + + $this->info('Imported '. $count.' airlines'); + } + + /** + * Imported the aircraft + */ + protected function importAircraft() + { + $this->comment('--- AIRCRAFT IMPORT ---'); + + $subfleet = Subfleet::where('name', self::SUBFLEET_NAME) + ->first(); + + if($subfleet === null) { + $this->info('Subfleet not found, inserting'); + $this->saveModel(new Subfleet([ + 'name' => self::SUBFLEET_NAME, + 'type' => 'PHPVMS' + ])); + } + + $this->info('Subfleet ID is '.$subfleet->id); + + $count = 0; + foreach($this->readRows('aircraft') as $row) + { + $this->aircraft[$row->id] = $row; + + $attrs = [ + 'subfleet_id' => $subfleet->id, + 'icao' => $row->icao, + 'name' => $row->fullname, + 'registration' => $row->registration, + 'active' => $row->enabled + ]; + + if ($this->saveModel(new Aircraft($attrs))) { + ++$count; + } + } + + $this->info('Imported ' . $count . ' aircraft'); + } + + /** + * Import all of the airports + */ + protected function importAirports() + { + $this->comment('--- AIRPORT IMPORT ---'); + + $count = 0; + foreach ($this->readRows('airports') as $row) + { + $attrs = [ + 'id' => $row->icao, + 'icao' => $row->icao, + 'name' => $row->name, + 'country' => $row->country, + 'lat' => $row->lat, + 'lon' => $row->lng, + 'hub' => $row->hub, + ]; + + if($this->saveModel(new Airport($attrs))) { + ++$count; + } + } + + $this->info('Imported ' . $count . ' airports'); + } + + /** + * Import the flights and schedules + */ + protected function importFlights() + { + $this->comment('--- FLIGHT SCHEDULE IMPORT ---'); + + $count = 0; + foreach ($this->readRows('schedules') as $row) + { + + } + + $this->info('Imported ' . $count . ' flights'); + } + + /** + * Import all of the PIREPs + */ + protected function importPireps() + { + $this->comment('--- PIREP IMPORT ---'); + + $count = 0; + foreach ($this->readRows('pireps') as $row) + { + + } + + $this->info('Imported ' . $count . ' pireps'); + } + + protected function importUsers() + { + $this->comment('--- USER IMPORT ---'); + + $count = 0; + foreach ($this->readRows('pilots') as $row) + { + + } + + $this->info('Imported ' . $count . ' users'); + } + + /** + * Recalculate all of the user ranks + */ + protected function recalculateRanks() + { + $this->comment('--- RECALCULATING RANKS ---'); + } +} diff --git a/app/Database/migrations/2017_06_09_010621_create_aircrafts_table.php b/app/Database/migrations/2017_06_09_010621_create_aircrafts_table.php index 6c63bd39..ab903bd3 100644 --- a/app/Database/migrations/2017_06_09_010621_create_aircrafts_table.php +++ b/app/Database/migrations/2017_06_09_010621_create_aircrafts_table.php @@ -10,6 +10,7 @@ class CreateAircraftsTable extends Migration Schema::create('aircraft', function (Blueprint $table) { $table->increments('id'); $table->unsignedInteger('subfleet_id'); + $table->string('icao', 4)->nullable(); $table->string('airport_id', 5)->nullable(); $table->string('hex_code', 10)->nullable(); $table->string('name', 50); diff --git a/app/Database/migrations/2017_06_21_165410_create_ranks_table.php b/app/Database/migrations/2017_06_21_165410_create_ranks_table.php index a01835a6..4c04bc59 100644 --- a/app/Database/migrations/2017_06_21_165410_create_ranks_table.php +++ b/app/Database/migrations/2017_06_21_165410_create_ranks_table.php @@ -16,6 +16,7 @@ class CreateRanksTable extends Migration Schema::create('ranks', function (Blueprint $table) { $table->increments('id'); $table->string('name', 50); + $table->string('link')->nullable(); $table->unsignedInteger('hours')->default(0); $table->boolean('auto_approve_acars')->default(false); $table->boolean('auto_approve_manual')->default(false); diff --git a/app/Models/Aircraft.php b/app/Models/Aircraft.php index cbd77ed0..39473fc8 100644 --- a/app/Models/Aircraft.php +++ b/app/Models/Aircraft.php @@ -10,6 +10,7 @@ class Aircraft extends BaseModel 'subfleet_id', 'airport_id', 'name', + 'icao', 'registration', 'tail_number', 'active', diff --git a/app/Models/Rank.php b/app/Models/Rank.php index bff2040d..3dd4c343 100644 --- a/app/Models/Rank.php +++ b/app/Models/Rank.php @@ -13,6 +13,7 @@ class Rank extends BaseModel public $fillable = [ 'name', + 'link', 'hours', 'auto_approve_acars', 'auto_approve_manual', @@ -28,7 +29,7 @@ class Rank extends BaseModel ]; public static $rules = [ - 'name' => 'required|unique:ranks', + 'name' => 'required', 'hours' => 'required', ];