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',
];