* Refactor and add importer to Installer module #443 * Refactor for finances to use in import * Import groups into roles * Formatting * Formatting * Add interface in installer for import * Notes about importing * Check for installer folder * Formatting * Fix pirep->user mapping * Unused import * Formatting
This commit is contained in:
2
Makefile
2
Makefile
@@ -19,7 +19,7 @@ clean:
|
|||||||
@php artisan view:clear
|
@php artisan view:clear
|
||||||
@find bootstrap/cache -type f -not -name '.gitignore' -print0 | xargs -0 rm -rf
|
@find bootstrap/cache -type f -not -name '.gitignore' -print0 | xargs -0 rm -rf
|
||||||
|
|
||||||
@find storage/framework/cache/ -mindepth 1 -not -name '.gitignore' -print0 | xargs -0 rm -rf
|
@find storage/framework/cache/ -mindepth 1 -type f -not -name '.gitignore' -print0 | xargs -0 rm -rf
|
||||||
@find storage/framework/sessions/ -mindepth 1 -type f -not -name '.gitignore' -print0 | xargs -0 rm -rf
|
@find storage/framework/sessions/ -mindepth 1 -type f -not -name '.gitignore' -print0 | xargs -0 rm -rf
|
||||||
@find storage/framework/views/ -mindepth 1 -not -name '.gitignore' -print0 | xargs -0 rm -rf
|
@find storage/framework/views/ -mindepth 1 -not -name '.gitignore' -print0 | xargs -0 rm -rf
|
||||||
|
|
||||||
|
|||||||
95
app/Console/Commands/CreateConfigs.php
Normal file
95
app/Console/Commands/CreateConfigs.php
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Console\Commands;
|
||||||
|
|
||||||
|
use App;
|
||||||
|
use App\Contracts\Command;
|
||||||
|
use App\Services\Installer\SeederService;
|
||||||
|
use DatabaseSeeder;
|
||||||
|
use Modules\Installer\Services\ConfigService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the config files
|
||||||
|
*/
|
||||||
|
class CreateConfigs extends Command
|
||||||
|
{
|
||||||
|
protected $signature = 'phpvms:config {db_host} {db_name} {db_user} {db_pass}';
|
||||||
|
protected $description = 'Create the config files';
|
||||||
|
|
||||||
|
private $databaseSeeder;
|
||||||
|
private $seederSvc;
|
||||||
|
|
||||||
|
public function __construct(DatabaseSeeder $databaseSeeder, SeederService $seederSvc)
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
|
||||||
|
$this->databaseSeeder = $databaseSeeder;
|
||||||
|
$this->seederSvc = $seederSvc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run dev related commands
|
||||||
|
*
|
||||||
|
* @throws \Symfony\Component\HttpFoundation\File\Exception\FileException
|
||||||
|
*/
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
$this->writeConfigs();
|
||||||
|
|
||||||
|
// Reload the configuration
|
||||||
|
App::boot();
|
||||||
|
|
||||||
|
$this->info('Recreating database');
|
||||||
|
$this->call('database:create', [
|
||||||
|
'--reset' => true,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->info('Running migrations');
|
||||||
|
$this->call('migrate:fresh', [
|
||||||
|
'--seed' => true,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->seederSvc->syncAllSeeds();
|
||||||
|
|
||||||
|
$this->info('Done!');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rewrite the configuration files
|
||||||
|
*
|
||||||
|
* @throws \Symfony\Component\HttpFoundation\File\Exception\FileException
|
||||||
|
*/
|
||||||
|
protected function writeConfigs()
|
||||||
|
{
|
||||||
|
/** @var ConfigService $cfgSvc */
|
||||||
|
$cfgSvc = app(ConfigService::class);
|
||||||
|
|
||||||
|
$this->info('Removing the old config files');
|
||||||
|
|
||||||
|
// Remove the old files
|
||||||
|
$config_file = base_path('config.php');
|
||||||
|
if (file_exists($config_file)) {
|
||||||
|
unlink($config_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
$env_file = base_path('env.php');
|
||||||
|
if (file_exists($env_file)) {
|
||||||
|
unlink($env_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
//{name} {db_host} {db_name} {db_user} {db_pass}
|
||||||
|
|
||||||
|
$this->info('Regenerating the config files');
|
||||||
|
$cfgSvc->createConfigFiles([
|
||||||
|
'APP_ENV' => 'dev',
|
||||||
|
'SITE_NAME' => $this->argument('name'),
|
||||||
|
'DB_CONN' => 'mysql',
|
||||||
|
'DB_HOST' => $this->argument('db_host'),
|
||||||
|
'DB_NAME' => $this->argument('db_name'),
|
||||||
|
'DB_USER' => $this->argument('db_user'),
|
||||||
|
'DB_PASS' => $this->argument('db_pass'),
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->info('Config files generated!');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,13 +2,14 @@
|
|||||||
|
|
||||||
namespace App\Console\Commands;
|
namespace App\Console\Commands;
|
||||||
|
|
||||||
|
use App\Console\Services\Database;
|
||||||
use App\Contracts\Command;
|
use App\Contracts\Command;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
use Tivie\OS\Detector;
|
use Tivie\OS\Detector;
|
||||||
|
|
||||||
class CreateDatabase extends Command
|
class CreateDatabase extends Command
|
||||||
{
|
{
|
||||||
protected $signature = 'database:create {--reset} {--conn=?}';
|
protected $signature = 'database:create {--reset} {--migrate} {--conn=?}';
|
||||||
protected $description = 'Create a database';
|
protected $description = 'Create a database';
|
||||||
protected $os;
|
protected $os;
|
||||||
|
|
||||||
@@ -36,8 +37,7 @@ class CreateDatabase extends Command
|
|||||||
$user = config($dbkey.'username');
|
$user = config($dbkey.'username');
|
||||||
$pass = config($dbkey.'password');
|
$pass = config($dbkey.'password');
|
||||||
|
|
||||||
$dbSvc = new \App\Console\Services\Database();
|
$dbSvc = new Database();
|
||||||
|
|
||||||
$dsn = $dbSvc->createDsn($host, $port);
|
$dsn = $dbSvc->createDsn($host, $port);
|
||||||
Log::info('Connection string: '.$dsn);
|
Log::info('Connection string: '.$dsn);
|
||||||
|
|
||||||
|
|||||||
@@ -1,28 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Console\Commands;
|
|
||||||
|
|
||||||
use App\Contracts\Command;
|
|
||||||
|
|
||||||
class ImportFromClassic extends Command
|
|
||||||
{
|
|
||||||
protected $signature = 'phpvms:importer {db_host} {db_name} {db_user} {db_pass?} {table_prefix=phpvms_}';
|
|
||||||
protected $description = 'Import from an older version of phpVMS';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Run dev related commands
|
|
||||||
*/
|
|
||||||
public function handle()
|
|
||||||
{
|
|
||||||
$db_creds = [
|
|
||||||
'host' => $this->argument('db_host'),
|
|
||||||
'name' => $this->argument('db_name'),
|
|
||||||
'user' => $this->argument('db_user'),
|
|
||||||
'pass' => $this->argument('db_pass'),
|
|
||||||
'table_prefix' => $this->argument('table_prefix'),
|
|
||||||
];
|
|
||||||
|
|
||||||
$importerSvc = new \App\Console\Services\Importer($db_creds);
|
|
||||||
$importerSvc->run();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,704 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Console\Services;
|
|
||||||
|
|
||||||
use App\Facades\Utils;
|
|
||||||
use App\Models\Aircraft;
|
|
||||||
use App\Models\Airline;
|
|
||||||
use App\Models\Airport;
|
|
||||||
use App\Models\Enums\FlightType;
|
|
||||||
use App\Models\Enums\PirepSource;
|
|
||||||
use App\Models\Enums\UserState;
|
|
||||||
use App\Models\Flight;
|
|
||||||
use App\Models\Pirep;
|
|
||||||
use App\Models\Rank;
|
|
||||||
use App\Models\Subfleet;
|
|
||||||
use App\Models\User;
|
|
||||||
use Carbon\Carbon;
|
|
||||||
use Illuminate\Database\QueryException;
|
|
||||||
use Illuminate\Support\Facades\Hash;
|
|
||||||
use Illuminate\Support\Str;
|
|
||||||
use PDO;
|
|
||||||
use PDOException;
|
|
||||||
use Symfony\Component\Console\Output\ConsoleOutput;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class Importer
|
|
||||||
* TODO: Batch import
|
|
||||||
*/
|
|
||||||
class Importer
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Hold references
|
|
||||||
*/
|
|
||||||
private $mappedEntities = [];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hold the PDO connection to the old database
|
|
||||||
*
|
|
||||||
* @var
|
|
||||||
*/
|
|
||||||
private $conn;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
private $creds;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hold the instance of the console logger
|
|
||||||
*
|
|
||||||
* @var
|
|
||||||
*/
|
|
||||||
private $log;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* CONSTANTS
|
|
||||||
*/
|
|
||||||
public const BATCH_READ_ROWS = 300;
|
|
||||||
public const SUBFLEET_NAME = 'Imported Aircraft';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Importer constructor.
|
|
||||||
*
|
|
||||||
* @param $db_creds
|
|
||||||
*/
|
|
||||||
public function __construct($db_creds)
|
|
||||||
{
|
|
||||||
// Setup the logger
|
|
||||||
$this->log = new ConsoleOutput();
|
|
||||||
|
|
||||||
// The db credentials
|
|
||||||
$this->creds = array_merge([
|
|
||||||
'host' => '127.0.0.1',
|
|
||||||
'port' => 3306,
|
|
||||||
'name' => '',
|
|
||||||
'user' => '',
|
|
||||||
'pass' => '',
|
|
||||||
'table_prefix' => '',
|
|
||||||
], $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->findLastPireps();
|
|
||||||
$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('<comment>'.$message.'</comment>');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $message
|
|
||||||
*/
|
|
||||||
protected function error($message)
|
|
||||||
{
|
|
||||||
$this->log->writeln('<error>'.$message.'</error>');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string|array $message
|
|
||||||
*/
|
|
||||||
protected function info($message)
|
|
||||||
{
|
|
||||||
if (\is_array($message)) {
|
|
||||||
/* @noinspection ForgottenDebugOutputInspection */
|
|
||||||
print_r($message);
|
|
||||||
} else {
|
|
||||||
$this->log->writeln('<info>'.$message.'</info>');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the table name with the prefix
|
|
||||||
*
|
|
||||||
* @param $table
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
protected function tableName($table)
|
|
||||||
{
|
|
||||||
if ($this->creds['table_prefix'] !== false) {
|
|
||||||
return $this->creds['table_prefix'].$table;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $table;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param \Illuminate\Database\Eloquent\Model $model
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
protected function saveModel($model)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
$model->save();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
} catch (QueryException $e) {
|
|
||||||
if ($e->getCode() !== '23000') {
|
|
||||||
$this->error($e);
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new mapping between an old ID and the new one
|
|
||||||
*
|
|
||||||
* @param $entity
|
|
||||||
* @param $old_id
|
|
||||||
* @param $new_id
|
|
||||||
*/
|
|
||||||
protected function addMapping($entity, $old_id, $new_id)
|
|
||||||
{
|
|
||||||
if (!array_key_exists($entity, $this->mappedEntities)) {
|
|
||||||
$this->mappedEntities[$entity] = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->mappedEntities[$entity][$old_id] = $new_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the ID for a mapping
|
|
||||||
*
|
|
||||||
* @param $entity
|
|
||||||
* @param $old_id
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
protected function getMapping($entity, $old_id)
|
|
||||||
{
|
|
||||||
if (!array_key_exists($entity, $this->mappedEntities)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
$entity = $this->mappedEntities[$entity];
|
|
||||||
if (array_key_exists($old_id, $entity)) {
|
|
||||||
return $entity[$old_id];
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $date
|
|
||||||
*
|
|
||||||
* @return Carbon
|
|
||||||
*/
|
|
||||||
protected function parseDate($date)
|
|
||||||
{
|
|
||||||
$carbon = Carbon::parse($date);
|
|
||||||
|
|
||||||
return $carbon;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Take a decimal duration and convert it to minutes
|
|
||||||
*
|
|
||||||
* @param $duration
|
|
||||||
*
|
|
||||||
* @return float|int
|
|
||||||
*/
|
|
||||||
protected function convertDuration($duration)
|
|
||||||
{
|
|
||||||
if (strpos($duration, '.') !== false) {
|
|
||||||
$delim = '.';
|
|
||||||
} elseif (strpos($duration, ':')) {
|
|
||||||
$delim = ':';
|
|
||||||
} else {
|
|
||||||
// no delimiter, assume it's just a straight hour
|
|
||||||
return (int) $duration * 60;
|
|
||||||
}
|
|
||||||
|
|
||||||
$hm = explode($delim, $duration);
|
|
||||||
$hours = (int) $hm[0] * 60;
|
|
||||||
$mins = (int) $hm[1];
|
|
||||||
|
|
||||||
return $hours + $mins;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @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 (int) $rows;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read all the rows in a table, but read them in a batched manner
|
|
||||||
*
|
|
||||||
* @param string $table The name of the table
|
|
||||||
* @param null $read_rows Number of rows to read
|
|
||||||
*
|
|
||||||
* @return \Generator
|
|
||||||
*/
|
|
||||||
protected function readRows($table, $read_rows = null)
|
|
||||||
{
|
|
||||||
// Set the table prefix if it has been entered
|
|
||||||
$this->tableName($table);
|
|
||||||
|
|
||||||
$offset = 0;
|
|
||||||
if ($read_rows === null) {
|
|
||||||
$read_rows = self::BATCH_READ_ROWS;
|
|
||||||
}
|
|
||||||
|
|
||||||
$total_rows = $this->getTotalRows($table);
|
|
||||||
|
|
||||||
while ($offset < $total_rows) {
|
|
||||||
$rows_to_read = $offset + $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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the subfleet
|
|
||||||
*
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
protected function getSubfleet()
|
|
||||||
{
|
|
||||||
$airline = Airline::first();
|
|
||||||
$subfleet = Subfleet::firstOrCreate(
|
|
||||||
['airline_id' => $airline->id, 'name' => self::SUBFLEET_NAME],
|
|
||||||
['type' => 'PHPVMS']
|
|
||||||
);
|
|
||||||
|
|
||||||
return $subfleet;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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) {
|
|
||||||
$rank = Rank::firstOrCreate(
|
|
||||||
['name' => $row->rank],
|
|
||||||
['image_url' => $row->rankimage, 'hours' => $row->minhours]
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->addMapping('ranks', $row->rankid, $rank->id);
|
|
||||||
$this->addMapping('ranks', $row->rank, $rank->id);
|
|
||||||
|
|
||||||
if ($rank->wasRecentlyCreated) {
|
|
||||||
$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) {
|
|
||||||
$airline = Airline::firstOrCreate(
|
|
||||||
['icao' => $row->code],
|
|
||||||
['iata' => $row->code, 'name' => $row->name, 'active' => $row->enabled]
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->addMapping('airlines', $row->id, $airline->id);
|
|
||||||
$this->addMapping('airlines', $row->code, $airline->id);
|
|
||||||
|
|
||||||
if ($airline->wasRecentlyCreated) {
|
|
||||||
$count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->info('Imported '.$count.' airlines');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Imported the aircraft
|
|
||||||
*/
|
|
||||||
protected function importAircraft()
|
|
||||||
{
|
|
||||||
$this->comment('--- AIRCRAFT IMPORT ---');
|
|
||||||
|
|
||||||
$subfleet = $this->getSubfleet();
|
|
||||||
|
|
||||||
$this->info('Subfleet ID is '.$subfleet->id);
|
|
||||||
|
|
||||||
$count = 0;
|
|
||||||
foreach ($this->readRows('aircraft') as $row) {
|
|
||||||
$aircraft = Aircraft::firstOrCreate(
|
|
||||||
['name' => $row->fullname, 'registration' => $row->registration],
|
|
||||||
['icao' => $row->icao,
|
|
||||||
'subfleet_id' => $subfleet->id,
|
|
||||||
'active' => $row->enabled,
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->addMapping('aircraft', $row->id, $aircraft->id);
|
|
||||||
|
|
||||||
if ($aircraft->wasRecentlyCreated) {
|
|
||||||
$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' => trim($row->icao),
|
|
||||||
'icao' => trim($row->icao),
|
|
||||||
'name' => $row->name,
|
|
||||||
'country' => $row->country,
|
|
||||||
'lat' => $row->lat,
|
|
||||||
'lon' => $row->lng,
|
|
||||||
'hub' => $row->hub,
|
|
||||||
];
|
|
||||||
|
|
||||||
$airport = Airport::updateOrCreate(
|
|
||||||
['id' => $attrs['id']],
|
|
||||||
$attrs
|
|
||||||
);
|
|
||||||
|
|
||||||
if ($airport->wasRecentlyCreated) {
|
|
||||||
$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) {
|
|
||||||
$airline_id = $this->getMapping('airlines', $row->code);
|
|
||||||
|
|
||||||
$flight_num = trim($row->flightnum);
|
|
||||||
|
|
||||||
$attrs = [
|
|
||||||
'dpt_airport_id' => $row->depicao,
|
|
||||||
'arr_airport_id' => $row->arricao,
|
|
||||||
'route' => $row->route ?: '',
|
|
||||||
'distance' => round($row->distance ?: 0, 2),
|
|
||||||
'level' => $row->flightlevel ?: 0,
|
|
||||||
'dpt_time' => $row->deptime ?: '',
|
|
||||||
'arr_time' => $row->arrtime ?: '',
|
|
||||||
'flight_time' => $this->convertDuration($row->flighttime) ?: '',
|
|
||||||
'notes' => $row->notes ?: '',
|
|
||||||
'active' => $row->enabled ?: true,
|
|
||||||
];
|
|
||||||
|
|
||||||
try {
|
|
||||||
$flight = Flight::updateOrCreate(
|
|
||||||
['airline_id' => $airline_id, 'flight_number' => $flight_num],
|
|
||||||
$attrs
|
|
||||||
);
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
//$this->error($e);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->addMapping('flights', $row->id, $flight->id);
|
|
||||||
|
|
||||||
// TODO: deserialize route_details into ACARS table
|
|
||||||
|
|
||||||
if ($flight->wasRecentlyCreated) {
|
|
||||||
$count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$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) {
|
|
||||||
$pirep_id = $row->pirepid;
|
|
||||||
$user_id = $this->getMapping('users', $row->pilotid);
|
|
||||||
$airline_id = $this->getMapping('airlines', $row->code);
|
|
||||||
$aircraft_id = $this->getMapping('aircraft', $row->aircraft);
|
|
||||||
|
|
||||||
$attrs = [
|
|
||||||
//'id' => $pirep_id,
|
|
||||||
'user_id' => $user_id,
|
|
||||||
'airline_id' => $airline_id,
|
|
||||||
'aircraft_id' => $aircraft_id,
|
|
||||||
'flight_number' => $row->flightnum ?: '',
|
|
||||||
'dpt_airport_id' => $row->depicao,
|
|
||||||
'arr_airport_id' => $row->arricao,
|
|
||||||
'block_fuel' => $row->fuelused,
|
|
||||||
'route' => $row->route ?: '',
|
|
||||||
'source_name' => $row->source,
|
|
||||||
'created_at' => $this->parseDate($row->submitdate),
|
|
||||||
'updated_at' => $this->parseDate($row->modifieddate),
|
|
||||||
];
|
|
||||||
|
|
||||||
// Set the distance
|
|
||||||
$distance = round($row->distance ?: 0, 2);
|
|
||||||
$attrs['distance'] = $distance;
|
|
||||||
$attrs['planned_distance'] = $distance;
|
|
||||||
|
|
||||||
// Set the flight time properly
|
|
||||||
$duration = $this->convertDuration($row->flighttime_stamp);
|
|
||||||
$attrs['flight_time'] = $duration;
|
|
||||||
$attrs['planned_flight_time'] = $duration;
|
|
||||||
|
|
||||||
// Set how it was filed
|
|
||||||
if (strtoupper($row->source) === 'MANUAL') {
|
|
||||||
$attrs['source'] = PirepSource::MANUAL;
|
|
||||||
} else {
|
|
||||||
$attrs['source'] = PirepSource::ACARS;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the flight type
|
|
||||||
$row->flighttype = strtoupper($row->flighttype);
|
|
||||||
if ($row->flighttype === 'P') {
|
|
||||||
$attrs['flight_type'] = FlightType::SCHED_PAX;
|
|
||||||
} elseif ($row->flighttype === 'C') {
|
|
||||||
$attrs['flight_type'] = FlightType::SCHED_CARGO;
|
|
||||||
} else {
|
|
||||||
$attrs['flight_type'] = FlightType::CHARTER_PAX_ONLY;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the flight level of the PIREP is set
|
|
||||||
if (property_exists($row, 'flightlevel')) {
|
|
||||||
$attrs['level'] = $row->flightlevel;
|
|
||||||
} else {
|
|
||||||
$attrs['level'] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
$pirep = Pirep::updateOrCreate(
|
|
||||||
['id' => $pirep_id],
|
|
||||||
$attrs
|
|
||||||
);
|
|
||||||
|
|
||||||
$source = strtoupper($row->source);
|
|
||||||
if ($source === 'SMARTCARS') {
|
|
||||||
// TODO: Parse smartcars log into the acars table
|
|
||||||
} elseif ($source === 'KACARS') {
|
|
||||||
// TODO: Parse kACARS log into acars table
|
|
||||||
} elseif ($source === 'XACARS') {
|
|
||||||
// TODO: Parse XACARS log into acars table
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Add extra fields in as PIREP fields
|
|
||||||
$this->addMapping('pireps', $row->pirepid, $pirep->id);
|
|
||||||
|
|
||||||
if ($pirep->wasRecentlyCreated) {
|
|
||||||
$count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->info('Imported '.$count.' pireps');
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function importUsers()
|
|
||||||
{
|
|
||||||
$this->comment('--- USER IMPORT ---');
|
|
||||||
|
|
||||||
$count = 0;
|
|
||||||
foreach ($this->readRows('pilots', 50) as $row) {
|
|
||||||
// TODO: What to do about pilot ids
|
|
||||||
|
|
||||||
$name = $row->firstname.' '.$row->lastname;
|
|
||||||
|
|
||||||
$airline_id = $this->getMapping('airlines', $row->code);
|
|
||||||
$rank_id = $this->getMapping('ranks', $row->rank);
|
|
||||||
$state = $this->getUserState($row->retired);
|
|
||||||
|
|
||||||
$new_password = Str::random(60);
|
|
||||||
|
|
||||||
$attrs = [
|
|
||||||
'name' => $name,
|
|
||||||
'password' => Hash::make($new_password),
|
|
||||||
'api_key' => Utils::generateApiKey(),
|
|
||||||
'airline_id' => $airline_id,
|
|
||||||
'rank_id' => $rank_id,
|
|
||||||
'home_airport_id' => $row->hub,
|
|
||||||
'curr_airport_id' => $row->hub,
|
|
||||||
'flights' => (int) $row->totalflights,
|
|
||||||
'flight_time' => Utils::hoursToMinutes($row->totalhours),
|
|
||||||
'state' => $state,
|
|
||||||
'created_at' => $this->parseDate($row->joindate),
|
|
||||||
];
|
|
||||||
|
|
||||||
$user = User::updateOrCreate(
|
|
||||||
['email' => $row->email],
|
|
||||||
$attrs
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->addMapping('users', $row->pilotid, $user->id);
|
|
||||||
|
|
||||||
if ($user->wasRecentlyCreated) {
|
|
||||||
$count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->info('Imported '.$count.' users');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Go through and set the last PIREP ID for the users
|
|
||||||
*/
|
|
||||||
protected function findLastPireps()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Recalculate all of the user ranks
|
|
||||||
*/
|
|
||||||
protected function recalculateRanks()
|
|
||||||
{
|
|
||||||
/*$this->comment('--- RECALCULATING RANKS ---');*/
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the user's new state from their original state
|
|
||||||
*
|
|
||||||
* @param $state
|
|
||||||
*
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
protected function getUserState($state)
|
|
||||||
{
|
|
||||||
// TODO: This state might differ between simpilot and classic version
|
|
||||||
|
|
||||||
$state = (int) $state;
|
|
||||||
|
|
||||||
// Declare array of classic states
|
|
||||||
$phpvms_classic_states = [
|
|
||||||
'ACTIVE' => 0,
|
|
||||||
'INACTIVE' => 1,
|
|
||||||
'BANNED' => 2,
|
|
||||||
'ON_LEAVE' => 3,
|
|
||||||
];
|
|
||||||
|
|
||||||
// Decide which state they will be in accordance with v7
|
|
||||||
if ($state === $phpvms_classic_states['ACTIVE']) {
|
|
||||||
return UserState::ACTIVE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($state === $phpvms_classic_states['INACTIVE']) {
|
|
||||||
// TODO: Make an inactive state?
|
|
||||||
return UserState::REJECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($state === $phpvms_classic_states['BANNED']) {
|
|
||||||
return UserState::SUSPENDED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($state === $phpvms_classic_states['ON_LEAVE']) {
|
|
||||||
return UserState::ON_LEAVE;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->error('Unknown status: '.$state);
|
|
||||||
return UserState::ACTIVE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
11
app/Contracts/Middleware.php
Normal file
11
app/Contracts/Middleware.php
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Contracts;
|
||||||
|
|
||||||
|
use Closure;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
interface Middleware
|
||||||
|
{
|
||||||
|
public function handle(Request $request, Closure $next);
|
||||||
|
}
|
||||||
@@ -3,12 +3,13 @@
|
|||||||
namespace App\Contracts;
|
namespace App\Contracts;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class Model
|
|
||||||
*
|
|
||||||
* @property mixed $id
|
* @property mixed $id
|
||||||
* @property bool $skip_mutator
|
* @property bool $skip_mutator
|
||||||
*
|
*
|
||||||
* @method static where(array $array)
|
* @method static Model find(int $airline_id)
|
||||||
|
* @method static Model where(array $array)
|
||||||
|
* @method static Model updateOrCreate(array $array, array $attrs)
|
||||||
|
* @method static truncate()
|
||||||
*/
|
*/
|
||||||
abstract class Model extends \Illuminate\Database\Eloquent\Model
|
abstract class Model extends \Illuminate\Database\Eloquent\Model
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -28,28 +28,6 @@ class UsersAddPilotId extends Migration
|
|||||||
|
|
||||||
// Migrate the current pilot IDs
|
// Migrate the current pilot IDs
|
||||||
DB::update('UPDATE `users` SET `pilot_id`=`id`');
|
DB::update('UPDATE `users` SET `pilot_id`=`id`');
|
||||||
|
|
||||||
// Drop the old ID column and add a new one
|
|
||||||
/*Schema::table('users', function (Blueprint $table) {
|
|
||||||
$table->dropPrimary('users_id_primary');
|
|
||||||
$table->dropColumn('id');
|
|
||||||
$table->string('id', Model::ID_MAX_LENGTH)->primary();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Update the users to use the `pilot_id` (so we don't need to migrate data from other tables)
|
|
||||||
$users = DB::table('users')->get(['id']);
|
|
||||||
foreach ($users as $user) {
|
|
||||||
$user->id = $user->pilot_id;
|
|
||||||
$user->save();
|
|
||||||
}*/
|
|
||||||
|
|
||||||
// role_user
|
|
||||||
// permission_user
|
|
||||||
// sessions
|
|
||||||
// pireps
|
|
||||||
// bids
|
|
||||||
// news
|
|
||||||
// user_awards
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# All of the different permissions that can be assigned to roles
|
# All of the different permissions that can be assigned to roles
|
||||||
---
|
---
|
||||||
- name: admin-access
|
- name: admin-access
|
||||||
display_name: Admin Access
|
display_name: Administrator
|
||||||
description: Access the admin panel
|
description: Access the admin panel
|
||||||
- name: airlines
|
- name: airlines
|
||||||
display_name: Airlines
|
display_name: Airlines
|
||||||
|
|||||||
@@ -79,7 +79,8 @@ class DashboardController extends Controller
|
|||||||
$this->checkNewVersion();
|
$this->checkNewVersion();
|
||||||
|
|
||||||
return view('admin.dashboard.index', [
|
return view('admin.dashboard.index', [
|
||||||
'news' => $this->newsRepo->getLatest(),
|
'news' => $this->newsRepo->getLatest(),
|
||||||
|
// 'installer_enabled' => $installerEnabled,
|
||||||
'pending_pireps' => $this->pirepRepo->getPendingCount(),
|
'pending_pireps' => $this->pirepRepo->getPendingCount(),
|
||||||
'pending_users' => $this->userRepo->getPendingCount(),
|
'pending_users' => $this->userRepo->getPendingCount(),
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -7,29 +7,33 @@ use App\Http\Requests\CreateRoleRequest;
|
|||||||
use App\Http\Requests\UpdateRoleRequest;
|
use App\Http\Requests\UpdateRoleRequest;
|
||||||
use App\Repositories\PermissionsRepository;
|
use App\Repositories\PermissionsRepository;
|
||||||
use App\Repositories\RoleRepository;
|
use App\Repositories\RoleRepository;
|
||||||
use Flash;
|
use App\Services\RoleService;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\Response;
|
||||||
|
use Laracasts\Flash\Flash;
|
||||||
use Prettus\Repository\Criteria\RequestCriteria;
|
use Prettus\Repository\Criteria\RequestCriteria;
|
||||||
use Response;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class AirlinesController
|
|
||||||
*/
|
|
||||||
class RolesController extends Controller
|
class RolesController extends Controller
|
||||||
{
|
{
|
||||||
private $permsRepo;
|
private $permsRepo;
|
||||||
private $rolesRepo;
|
private $rolesRepo;
|
||||||
|
private $roleSvc;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AirlinesController constructor.
|
* AirlinesController constructor.
|
||||||
*
|
*
|
||||||
* @param PermissionsRepository $permsRepo
|
* @param PermissionsRepository $permsRepo
|
||||||
* @param RoleRepository $rolesRepo
|
* @param RoleRepository $rolesRepo
|
||||||
|
* @param $roleSvc
|
||||||
*/
|
*/
|
||||||
public function __construct(PermissionsRepository $permsRepo, RoleRepository $rolesRepo)
|
public function __construct(
|
||||||
{
|
PermissionsRepository $permsRepo,
|
||||||
|
RoleRepository $rolesRepo,
|
||||||
|
RoleService $roleSvc
|
||||||
|
) {
|
||||||
$this->permsRepo = $permsRepo;
|
$this->permsRepo = $permsRepo;
|
||||||
$this->rolesRepo = $rolesRepo;
|
$this->rolesRepo = $rolesRepo;
|
||||||
|
$this->roleSvc = $roleSvc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -132,8 +136,6 @@ class RolesController extends Controller
|
|||||||
* @param int $id
|
* @param int $id
|
||||||
* @param UpdateRoleRequest $request
|
* @param UpdateRoleRequest $request
|
||||||
*
|
*
|
||||||
* @throws \Prettus\Validator\Exceptions\ValidatorException
|
|
||||||
*
|
|
||||||
* @return Response
|
* @return Response
|
||||||
*/
|
*/
|
||||||
public function update($id, UpdateRoleRequest $request)
|
public function update($id, UpdateRoleRequest $request)
|
||||||
@@ -145,14 +147,8 @@ class RolesController extends Controller
|
|||||||
return redirect(route('admin.roles.index'));
|
return redirect(route('admin.roles.index'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->rolesRepo->update($request->all(), $id);
|
$this->roleSvc->updateRole($role, $request->all());
|
||||||
|
$this->roleSvc->setPermissionsForRole($role, $request->permissions);
|
||||||
// Update the permissions, filter out null/invalid values
|
|
||||||
$perms = collect($request->permissions)->filter(static function ($v, $k) {
|
|
||||||
return $v;
|
|
||||||
});
|
|
||||||
|
|
||||||
$role->permissions()->sync($perms);
|
|
||||||
|
|
||||||
Flash::success('Roles updated successfully.');
|
Flash::success('Roles updated successfully.');
|
||||||
return redirect(route('admin.roles.index'));
|
return redirect(route('admin.roles.index'));
|
||||||
|
|||||||
@@ -5,12 +5,14 @@
|
|||||||
|
|
||||||
namespace App\Http\Middleware;
|
namespace App\Http\Middleware;
|
||||||
|
|
||||||
|
use App\Contracts\Middleware;
|
||||||
use App\Models\Enums\UserState;
|
use App\Models\Enums\UserState;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Auth;
|
|
||||||
use Closure;
|
use Closure;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
|
||||||
class ApiAuth
|
class ApiAuth implements Middleware
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Handle an incoming request.
|
* Handle an incoming request.
|
||||||
@@ -20,7 +22,7 @@ class ApiAuth
|
|||||||
*
|
*
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function handle($request, Closure $next)
|
public function handle(Request $request, Closure $next)
|
||||||
{
|
{
|
||||||
// Check if Authorization header is in place
|
// Check if Authorization header is in place
|
||||||
$api_key = $request->header('x-api-key', null);
|
$api_key = $request->header('x-api-key', null);
|
||||||
|
|||||||
@@ -2,9 +2,10 @@
|
|||||||
|
|
||||||
namespace App\Http\Middleware;
|
namespace App\Http\Middleware;
|
||||||
|
|
||||||
|
use App\Contracts\Middleware;
|
||||||
use Illuminate\Cookie\Middleware\EncryptCookies as BaseEncrypter;
|
use Illuminate\Cookie\Middleware\EncryptCookies as BaseEncrypter;
|
||||||
|
|
||||||
class EncryptCookies extends BaseEncrypter
|
class EncryptCookies extends BaseEncrypter implements Middleware
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* The names of the cookies that should not be encrypted.
|
* The names of the cookies that should not be encrypted.
|
||||||
|
|||||||
@@ -5,17 +5,18 @@
|
|||||||
|
|
||||||
namespace App\Http\Middleware;
|
namespace App\Http\Middleware;
|
||||||
|
|
||||||
|
use App\Contracts\Middleware;
|
||||||
use Closure;
|
use Closure;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
class InstalledCheck
|
/**
|
||||||
|
* Check the app.key to see whether we're installed or not
|
||||||
|
*
|
||||||
|
* If the default key is set and we're not in any of the installer routes
|
||||||
|
* show the message that we need to be installed
|
||||||
|
*/
|
||||||
|
class InstalledCheck implements Middleware
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* Check the app.key to see whether we're installed or not
|
|
||||||
*
|
|
||||||
* If the default key is set and we're not in any of the installer routes
|
|
||||||
* show the message that we need to be installed
|
|
||||||
*/
|
|
||||||
public function handle(Request $request, Closure $next)
|
public function handle(Request $request, Closure $next)
|
||||||
{
|
{
|
||||||
if (config('app.key') === 'base64:zdgcDqu9PM8uGWCtMxd74ZqdGJIrnw812oRMmwDF6KY='
|
if (config('app.key') === 'base64:zdgcDqu9PM8uGWCtMxd74ZqdGJIrnw812oRMmwDF6KY='
|
||||||
|
|||||||
@@ -5,11 +5,13 @@
|
|||||||
|
|
||||||
namespace App\Http\Middleware;
|
namespace App\Http\Middleware;
|
||||||
|
|
||||||
|
use App\Contracts\Middleware;
|
||||||
use Closure;
|
use Closure;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
class JsonResponse
|
class JsonResponse implements Middleware
|
||||||
{
|
{
|
||||||
public function handle($request, Closure $next)
|
public function handle(Request $request, Closure $next)
|
||||||
{
|
{
|
||||||
$response = $next($request);
|
$response = $next($request);
|
||||||
$response->headers->set('Content-Type', 'application/json');
|
$response->headers->set('Content-Type', 'application/json');
|
||||||
|
|||||||
@@ -5,19 +5,13 @@
|
|||||||
|
|
||||||
namespace App\Http\Middleware;
|
namespace App\Http\Middleware;
|
||||||
|
|
||||||
|
use App\Contracts\Middleware;
|
||||||
use Closure;
|
use Closure;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
class MeasureExecutionTime
|
class MeasureExecutionTime implements Middleware
|
||||||
{
|
{
|
||||||
/**
|
public function handle(Request $request, Closure $next)
|
||||||
* Handle an incoming request.
|
|
||||||
*
|
|
||||||
* @param \Illuminate\Http\Request $request
|
|
||||||
* @param \Closure $next
|
|
||||||
*
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function handle($request, Closure $next)
|
|
||||||
{
|
{
|
||||||
// Get the response
|
// Get the response
|
||||||
$response = $next($request);
|
$response = $next($request);
|
||||||
|
|||||||
@@ -2,21 +2,14 @@
|
|||||||
|
|
||||||
namespace App\Http\Middleware;
|
namespace App\Http\Middleware;
|
||||||
|
|
||||||
|
use App\Contracts\Middleware;
|
||||||
use Closure;
|
use Closure;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
|
||||||
class RedirectIfAuthenticated
|
class RedirectIfAuthenticated implements Middleware
|
||||||
{
|
{
|
||||||
/**
|
public function handle(Request $request, Closure $next, $guard = null)
|
||||||
* Handle an incoming request.
|
|
||||||
*
|
|
||||||
* @param \Illuminate\Http\Request $request
|
|
||||||
* @param \Closure $next
|
|
||||||
* @param string|null $guard
|
|
||||||
*
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function handle($request, Closure $next, $guard = null)
|
|
||||||
{
|
{
|
||||||
if (Auth::guard($guard)->check()) {
|
if (Auth::guard($guard)->check()) {
|
||||||
return redirect('/');
|
return redirect('/');
|
||||||
|
|||||||
@@ -2,15 +2,17 @@
|
|||||||
|
|
||||||
namespace App\Http\Middleware;
|
namespace App\Http\Middleware;
|
||||||
|
|
||||||
|
use App\Contracts\Middleware;
|
||||||
use Closure;
|
use Closure;
|
||||||
use Igaster\LaravelTheme\Facades\Theme;
|
use Igaster\LaravelTheme\Facades\Theme;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read the current theme from the settings (set in admin), and set it
|
* Read the current theme from the settings (set in admin), and set it
|
||||||
*/
|
*/
|
||||||
class SetActiveTheme
|
class SetActiveTheme implements Middleware
|
||||||
{
|
{
|
||||||
public function handle($request, Closure $next)
|
public function handle(Request $request, Closure $next)
|
||||||
{
|
{
|
||||||
$theme = setting('general.theme');
|
$theme = setting('general.theme');
|
||||||
if (!empty($theme)) {
|
if (!empty($theme)) {
|
||||||
|
|||||||
@@ -2,13 +2,15 @@
|
|||||||
|
|
||||||
namespace App\Http\Middleware;
|
namespace App\Http\Middleware;
|
||||||
|
|
||||||
|
use App\Contracts\Middleware;
|
||||||
use App\Services\Installer\InstallerService;
|
use App\Services\Installer\InstallerService;
|
||||||
use Closure;
|
use Closure;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if an update is pending by checking in with the Installer service
|
* Determine if an update is pending by checking in with the Installer service
|
||||||
*/
|
*/
|
||||||
class UpdatePending
|
class UpdatePending implements Middleware
|
||||||
{
|
{
|
||||||
private $installerSvc;
|
private $installerSvc;
|
||||||
|
|
||||||
@@ -17,13 +19,7 @@ class UpdatePending
|
|||||||
$this->installerSvc = $installerSvc;
|
$this->installerSvc = $installerSvc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function handle(Request $request, Closure $next)
|
||||||
* @param \Illuminate\Http\Request $request
|
|
||||||
* @param \Closure $next
|
|
||||||
*
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function handle($request, Closure $next)
|
|
||||||
{
|
{
|
||||||
if ($this->installerSvc->isUpgradePending()) {
|
if ($this->installerSvc->isUpgradePending()) {
|
||||||
return redirect('/update/step1');
|
return redirect('/update/step1');
|
||||||
|
|||||||
@@ -2,9 +2,10 @@
|
|||||||
|
|
||||||
namespace App\Http\Middleware;
|
namespace App\Http\Middleware;
|
||||||
|
|
||||||
|
use App\Contracts\Middleware;
|
||||||
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as BaseVerifier;
|
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as BaseVerifier;
|
||||||
|
|
||||||
class VerifyCsrfToken extends BaseVerifier
|
class VerifyCsrfToken extends BaseVerifier implements Middleware
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* The URIs that should be excluded from CSRF verification.
|
* The URIs that should be excluded from CSRF verification.
|
||||||
|
|||||||
@@ -4,6 +4,9 @@ namespace App\Models;
|
|||||||
|
|
||||||
use Laratrust\Models\LaratrustPermission;
|
use Laratrust\Models\LaratrustPermission;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @method static firstOrCreate(array $array, array $array1)
|
||||||
|
*/
|
||||||
class Permission extends LaratrustPermission
|
class Permission extends LaratrustPermission
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ use Laratrust\Models\LaratrustRole;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @method static where(string $string, $group)
|
* @method static where(string $string, $group)
|
||||||
|
* @method static firstOrCreate(array $array, array $array1)
|
||||||
|
* @method static truncate()
|
||||||
*/
|
*/
|
||||||
class Role extends LaratrustRole
|
class Role extends LaratrustRole
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -34,6 +34,10 @@ use Laratrust\Traits\LaratrustUserTrait;
|
|||||||
* @property int state
|
* @property int state
|
||||||
* @property bool opt_in
|
* @property bool opt_in
|
||||||
* @property string last_pirep_id
|
* @property string last_pirep_id
|
||||||
|
*
|
||||||
|
* @method static updateOrCreate(array $array, array $attrs)
|
||||||
|
* @method static where()
|
||||||
|
* @method static truncate()
|
||||||
* @mixin \Illuminate\Notifications\Notifiable
|
* @mixin \Illuminate\Notifications\Notifiable
|
||||||
* @mixin \Laratrust\Traits\LaratrustUserTrait
|
* @mixin \Laratrust\Traits\LaratrustUserTrait
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -26,8 +26,8 @@ use App\Models\User;
|
|||||||
use App\Repositories\SettingRepository;
|
use App\Repositories\SettingRepository;
|
||||||
use App\Services\ModuleService;
|
use App\Services\ModuleService;
|
||||||
use Illuminate\Support\Facades\Schema;
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
use Illuminate\Support\Facades\View;
|
||||||
use Illuminate\Support\ServiceProvider;
|
use Illuminate\Support\ServiceProvider;
|
||||||
use View;
|
|
||||||
|
|
||||||
class AppServiceProvider extends ServiceProvider
|
class AppServiceProvider extends ServiceProvider
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -11,17 +11,16 @@ use App\Models\Pirep;
|
|||||||
use App\Repositories\ExpenseRepository;
|
use App\Repositories\ExpenseRepository;
|
||||||
use App\Repositories\JournalRepository;
|
use App\Repositories\JournalRepository;
|
||||||
use App\Services\FareService;
|
use App\Services\FareService;
|
||||||
|
use App\Services\FinanceService;
|
||||||
use App\Support\Math;
|
use App\Support\Math;
|
||||||
use App\Support\Money;
|
use App\Support\Money;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
/**
|
|
||||||
* Class FinanceService
|
|
||||||
*/
|
|
||||||
class PirepFinanceService extends Service
|
class PirepFinanceService extends Service
|
||||||
{
|
{
|
||||||
private $expenseRepo;
|
private $expenseRepo;
|
||||||
private $fareSvc;
|
private $fareSvc;
|
||||||
|
private $financeSvc;
|
||||||
private $journalRepo;
|
private $journalRepo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -30,15 +29,18 @@ class PirepFinanceService extends Service
|
|||||||
* @param ExpenseRepository $expenseRepo
|
* @param ExpenseRepository $expenseRepo
|
||||||
* @param FareService $fareSvc
|
* @param FareService $fareSvc
|
||||||
* @param JournalRepository $journalRepo
|
* @param JournalRepository $journalRepo
|
||||||
|
* @param FinanceService $financeSvc
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
ExpenseRepository $expenseRepo,
|
ExpenseRepository $expenseRepo,
|
||||||
FareService $fareSvc,
|
FareService $fareSvc,
|
||||||
|
FinanceService $financeSvc,
|
||||||
JournalRepository $journalRepo
|
JournalRepository $journalRepo
|
||||||
) {
|
) {
|
||||||
$this->expenseRepo = $expenseRepo;
|
$this->expenseRepo = $expenseRepo;
|
||||||
$this->fareSvc = $fareSvc;
|
$this->fareSvc = $fareSvc;
|
||||||
$this->journalRepo = $journalRepo;
|
$this->journalRepo = $journalRepo;
|
||||||
|
$this->financeSvc = $financeSvc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -149,13 +151,11 @@ class PirepFinanceService extends Service
|
|||||||
Log::info('Finance: Fuel cost, (fuel='.$fuel_used.', cost='.$ap->fuel_jeta_cost.') D='
|
Log::info('Finance: Fuel cost, (fuel='.$fuel_used.', cost='.$ap->fuel_jeta_cost.') D='
|
||||||
.$debit->getAmount());
|
.$debit->getAmount());
|
||||||
|
|
||||||
$this->journalRepo->post(
|
$this->financeSvc->debitFromJournal(
|
||||||
$pirep->airline->journal,
|
$pirep->airline->journal,
|
||||||
null,
|
|
||||||
$debit,
|
$debit,
|
||||||
$pirep,
|
$pirep,
|
||||||
'Fuel Cost ('.$ap->fuel_jeta_cost.'/'.config('phpvms.internal_units.fuel').')',
|
'Fuel Cost ('.$ap->fuel_jeta_cost.'/'.config('phpvms.internal_units.fuel').')',
|
||||||
null,
|
|
||||||
'Fuel',
|
'Fuel',
|
||||||
'fuel'
|
'fuel'
|
||||||
);
|
);
|
||||||
@@ -194,13 +194,11 @@ class PirepFinanceService extends Service
|
|||||||
$debit = Money::createFromAmount($cost_per_min * $block_time);
|
$debit = Money::createFromAmount($cost_per_min * $block_time);
|
||||||
Log::info('Finance: Subfleet Block Hourly, D='.$debit->getAmount());
|
Log::info('Finance: Subfleet Block Hourly, D='.$debit->getAmount());
|
||||||
|
|
||||||
$this->journalRepo->post(
|
$this->financeSvc->debitFromJournal(
|
||||||
$pirep->airline->journal,
|
$pirep->airline->journal,
|
||||||
null,
|
|
||||||
$debit,
|
$debit,
|
||||||
$pirep,
|
$pirep,
|
||||||
'Subfleet '.$sf->type.': Block Time Cost',
|
'Subfleet '.$sf->type.': Block Time Cost',
|
||||||
null,
|
|
||||||
'Subfleet '.$sf->type,
|
'Subfleet '.$sf->type,
|
||||||
'subfleet'
|
'subfleet'
|
||||||
);
|
);
|
||||||
@@ -265,13 +263,11 @@ class PirepFinanceService extends Service
|
|||||||
$journal = $pirep->user->journal;
|
$journal = $pirep->user->journal;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->journalRepo->post(
|
$this->financeSvc->debitFromJournal(
|
||||||
$journal,
|
$journal,
|
||||||
null,
|
|
||||||
$debit,
|
$debit,
|
||||||
$pirep,
|
$pirep,
|
||||||
$memo,
|
$memo,
|
||||||
null,
|
|
||||||
$transaction_group,
|
$transaction_group,
|
||||||
strtolower($klass)
|
strtolower($klass)
|
||||||
);
|
);
|
||||||
@@ -320,13 +316,11 @@ class PirepFinanceService extends Service
|
|||||||
|
|
||||||
$debit = Money::createFromAmount($expense->amount);
|
$debit = Money::createFromAmount($expense->amount);
|
||||||
|
|
||||||
$this->journalRepo->post(
|
$this->financeSvc->debitFromJournal(
|
||||||
$pirep->airline->journal,
|
$pirep->airline->journal,
|
||||||
null,
|
|
||||||
$debit,
|
$debit,
|
||||||
$pirep,
|
$pirep,
|
||||||
'Expense: '.$expense->name,
|
'Expense: '.$expense->name,
|
||||||
null,
|
|
||||||
$expense->transaction_group ?? 'Expenses',
|
$expense->transaction_group ?? 'Expenses',
|
||||||
'expense'
|
'expense'
|
||||||
);
|
);
|
||||||
@@ -347,13 +341,12 @@ class PirepFinanceService extends Service
|
|||||||
{
|
{
|
||||||
$ground_handling_cost = $this->getGroundHandlingCost($pirep);
|
$ground_handling_cost = $this->getGroundHandlingCost($pirep);
|
||||||
Log::info('Finance: PIREP: '.$pirep->id.'; ground handling: '.$ground_handling_cost);
|
Log::info('Finance: PIREP: '.$pirep->id.'; ground handling: '.$ground_handling_cost);
|
||||||
$this->journalRepo->post(
|
|
||||||
|
$this->financeSvc->debitFromJournal(
|
||||||
$pirep->airline->journal,
|
$pirep->airline->journal,
|
||||||
null,
|
|
||||||
Money::createFromAmount($ground_handling_cost),
|
Money::createFromAmount($ground_handling_cost),
|
||||||
$pirep,
|
$pirep,
|
||||||
'Ground Handling',
|
'Ground Handling',
|
||||||
null,
|
|
||||||
'Ground Handling',
|
'Ground Handling',
|
||||||
'ground_handling'
|
'ground_handling'
|
||||||
);
|
);
|
||||||
@@ -378,24 +371,20 @@ class PirepFinanceService extends Service
|
|||||||
Log::info('Finance: PIREP: '.$pirep->id
|
Log::info('Finance: PIREP: '.$pirep->id
|
||||||
.'; pilot pay: '.$pilot_pay_rate.', total: '.$pilot_pay);
|
.'; pilot pay: '.$pilot_pay_rate.', total: '.$pilot_pay);
|
||||||
|
|
||||||
$this->journalRepo->post(
|
$this->financeSvc->debitFromJournal(
|
||||||
$pirep->airline->journal,
|
$pirep->airline->journal,
|
||||||
null,
|
|
||||||
$pilot_pay,
|
$pilot_pay,
|
||||||
$pirep,
|
$pirep,
|
||||||
$memo,
|
$memo,
|
||||||
null,
|
|
||||||
'Pilot Pay',
|
'Pilot Pay',
|
||||||
'pilot_pay'
|
'pilot_pay'
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->journalRepo->post(
|
$this->financeSvc->creditToJournal(
|
||||||
$pirep->user->journal,
|
$pirep->user->journal,
|
||||||
$pilot_pay,
|
$pilot_pay,
|
||||||
null,
|
|
||||||
$pirep,
|
$pirep,
|
||||||
$memo,
|
$memo,
|
||||||
null,
|
|
||||||
'Pilot Pay',
|
'Pilot Pay',
|
||||||
'pilot_pay'
|
'pilot_pay'
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -8,23 +8,22 @@ use App\Models\Enums\ExpenseType;
|
|||||||
use App\Models\Expense;
|
use App\Models\Expense;
|
||||||
use App\Models\JournalTransaction;
|
use App\Models\JournalTransaction;
|
||||||
use App\Repositories\JournalRepository;
|
use App\Repositories\JournalRepository;
|
||||||
|
use App\Services\FinanceService;
|
||||||
use App\Support\Money;
|
use App\Support\Money;
|
||||||
use Log;
|
use Carbon\Carbon;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process all of the daily expenses and charge them
|
* Process all of the daily expenses and charge them
|
||||||
*/
|
*/
|
||||||
class RecurringFinanceService extends Service
|
class RecurringFinanceService extends Service
|
||||||
{
|
{
|
||||||
|
private $financeSvc;
|
||||||
private $journalRepo;
|
private $journalRepo;
|
||||||
|
|
||||||
/**
|
public function __construct(JournalRepository $journalRepo, FinanceService $financeSvc)
|
||||||
* RecurringFinanceService constructor.
|
|
||||||
*
|
|
||||||
* @param JournalRepository $journalRepo
|
|
||||||
*/
|
|
||||||
public function __construct(JournalRepository $journalRepo)
|
|
||||||
{
|
{
|
||||||
|
$this->financeSvc = $financeSvc;
|
||||||
$this->journalRepo = $journalRepo;
|
$this->journalRepo = $journalRepo;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,10 +86,8 @@ class RecurringFinanceService extends Service
|
|||||||
/**
|
/**
|
||||||
* Run all of the daily expense/financials
|
* Run all of the daily expense/financials
|
||||||
*
|
*
|
||||||
* @param int $type
|
* @param string $type
|
||||||
*
|
*
|
||||||
* @throws \UnexpectedValueException
|
|
||||||
* @throws \InvalidArgumentException
|
|
||||||
* @throws \Prettus\Validator\Exceptions\ValidatorException
|
* @throws \Prettus\Validator\Exceptions\ValidatorException
|
||||||
*/
|
*/
|
||||||
public function processExpenses($type = ExpenseType::DAILY): void
|
public function processExpenses($type = ExpenseType::DAILY): void
|
||||||
@@ -101,7 +98,7 @@ class RecurringFinanceService extends Service
|
|||||||
if ($type === ExpenseType::DAILY) {
|
if ($type === ExpenseType::DAILY) {
|
||||||
$tag = 'expenses_daily';
|
$tag = 'expenses_daily';
|
||||||
} elseif ($type === ExpenseType::MONTHLY) {
|
} elseif ($type === ExpenseType::MONTHLY) {
|
||||||
$tag === 'expenses_monthly';
|
$tag = 'expenses_monthly';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -122,7 +119,7 @@ class RecurringFinanceService extends Service
|
|||||||
];
|
];
|
||||||
|
|
||||||
$found = JournalTransaction::where($w)
|
$found = JournalTransaction::where($w)
|
||||||
->whereDate('post_date', '=', \Carbon::now('UTC')->toDateString())
|
->whereDate('post_date', '=', Carbon::now('UTC')->toDateString())
|
||||||
->count(['id']);
|
->count(['id']);
|
||||||
|
|
||||||
if ($found > 0) {
|
if ($found > 0) {
|
||||||
@@ -132,13 +129,11 @@ class RecurringFinanceService extends Service
|
|||||||
|
|
||||||
[$memo, $ta_group] = $this->getMemoAndGroup($expense);
|
[$memo, $ta_group] = $this->getMemoAndGroup($expense);
|
||||||
|
|
||||||
$this->journalRepo->post(
|
$this->financeSvc->debitFromJournal(
|
||||||
$journal,
|
$journal,
|
||||||
null,
|
|
||||||
Money::createFromAmount($amount),
|
Money::createFromAmount($amount),
|
||||||
$expense,
|
$expense,
|
||||||
$memo,
|
$memo,
|
||||||
null,
|
|
||||||
$ta_group,
|
$ta_group,
|
||||||
$tag
|
$tag
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -4,11 +4,93 @@ namespace App\Services;
|
|||||||
|
|
||||||
use App\Contracts\Service;
|
use App\Contracts\Service;
|
||||||
use App\Models\Airline;
|
use App\Models\Airline;
|
||||||
|
use App\Models\Journal;
|
||||||
use App\Models\JournalTransaction;
|
use App\Models\JournalTransaction;
|
||||||
|
use App\Repositories\JournalRepository;
|
||||||
use App\Support\Money;
|
use App\Support\Money;
|
||||||
|
|
||||||
class FinanceService extends Service
|
class FinanceService extends Service
|
||||||
{
|
{
|
||||||
|
private $journalRepo;
|
||||||
|
|
||||||
|
public function __construct(JournalRepository $journalRepo)
|
||||||
|
{
|
||||||
|
$this->journalRepo = $journalRepo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Credit some amount to a given journal
|
||||||
|
* E.g, some amount for expenses or ground handling fees, etc. Example, to pay a user a dollar
|
||||||
|
* for a pirep:
|
||||||
|
*
|
||||||
|
* creditToJournal($user->journal, new Money(1000), $pirep, 'Payment', 'pirep', 'payment');
|
||||||
|
*
|
||||||
|
* @param \App\Models\Journal $journal
|
||||||
|
* @param Money $amount
|
||||||
|
* @param \Illuminate\Database\Eloquent\Model $reference
|
||||||
|
* @param string $memo
|
||||||
|
* @param string $transaction_group
|
||||||
|
* @param string|array $tag
|
||||||
|
*
|
||||||
|
* @throws \Prettus\Validator\Exceptions\ValidatorException
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function creditToJournal(
|
||||||
|
Journal $journal,
|
||||||
|
Money $amount,
|
||||||
|
$reference,
|
||||||
|
$memo,
|
||||||
|
$transaction_group,
|
||||||
|
$tag
|
||||||
|
) {
|
||||||
|
return $this->journalRepo->post(
|
||||||
|
$journal,
|
||||||
|
$amount,
|
||||||
|
null,
|
||||||
|
$reference,
|
||||||
|
$memo,
|
||||||
|
null,
|
||||||
|
$transaction_group,
|
||||||
|
$tag
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Charge some expense for a given PIREP to the airline its file against
|
||||||
|
* E.g, some amount for expenses or ground handling fees, etc.
|
||||||
|
*
|
||||||
|
* @param \App\Models\Journal $journal
|
||||||
|
* @param Money $amount
|
||||||
|
* @param \Illuminate\Database\Eloquent\Model $reference
|
||||||
|
* @param string $memo
|
||||||
|
* @param string $transaction_group
|
||||||
|
* @param string|array $tag
|
||||||
|
*
|
||||||
|
* @throws \Prettus\Validator\Exceptions\ValidatorException
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function debitFromJournal(
|
||||||
|
Journal $journal,
|
||||||
|
Money $amount,
|
||||||
|
$reference,
|
||||||
|
$memo,
|
||||||
|
$transaction_group,
|
||||||
|
$tag
|
||||||
|
) {
|
||||||
|
return $this->journalRepo->post(
|
||||||
|
$journal,
|
||||||
|
null,
|
||||||
|
$amount,
|
||||||
|
$reference,
|
||||||
|
$memo,
|
||||||
|
null,
|
||||||
|
$transaction_group,
|
||||||
|
$tag
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all of the transactions for an airline between two given dates. Returns an array
|
* Get all of the transactions for an airline between two given dates. Returns an array
|
||||||
* with `credits`, `debits` and `transactions` fields, where transactions contains the
|
* with `credits`, `debits` and `transactions` fields, where transactions contains the
|
||||||
|
|||||||
@@ -236,6 +236,15 @@ class SeederService extends Service
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// See if any of these column values have changed
|
||||||
|
foreach (['name', 'description'] as $column) {
|
||||||
|
$currVal = $row->{$column};
|
||||||
|
$newVal = $setting[$column];
|
||||||
|
if ($currVal !== $newVal) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// See if any of the options have changed
|
// See if any of the options have changed
|
||||||
if ($row->type === 'select') {
|
if ($row->type === 'select') {
|
||||||
if ($row->options !== $setting['options']) {
|
if ($row->options !== $setting['options']) {
|
||||||
@@ -259,10 +268,20 @@ class SeederService extends Service
|
|||||||
$yml = Yaml::parse($data);
|
$yml = Yaml::parse($data);
|
||||||
|
|
||||||
foreach ($yml as $perm) {
|
foreach ($yml as $perm) {
|
||||||
$count = DB::table('permissions')->where('name', $perm['name'])->count('name');
|
$row = DB::table('permissions')
|
||||||
if ($count === 0) {
|
->where('name', $perm['name'])
|
||||||
|
->first();
|
||||||
|
|
||||||
|
if (!$row) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// See if any of these column values have changed
|
||||||
|
foreach (['display_name', 'description'] as $column) {
|
||||||
|
if ($row->{$column} !== $perm[$column]) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
47
app/Services/RoleService.php
Normal file
47
app/Services/RoleService.php
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Services;
|
||||||
|
|
||||||
|
use App\Contracts\Service;
|
||||||
|
use App\Models\Role;
|
||||||
|
use App\Repositories\RoleRepository;
|
||||||
|
|
||||||
|
class RoleService extends Service
|
||||||
|
{
|
||||||
|
private $roleRepo;
|
||||||
|
|
||||||
|
public function __construct(RoleRepository $roleRepo)
|
||||||
|
{
|
||||||
|
$this->roleRepo = $roleRepo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update a role with the given attributes
|
||||||
|
*
|
||||||
|
* @param Role $role
|
||||||
|
* @param array $attrs
|
||||||
|
*
|
||||||
|
* @return Role
|
||||||
|
*/
|
||||||
|
public function updateRole(Role $role, array $attrs)
|
||||||
|
{
|
||||||
|
$role->update($attrs);
|
||||||
|
$role->save();
|
||||||
|
|
||||||
|
return $role;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Role $role
|
||||||
|
* @param array $permissions
|
||||||
|
*/
|
||||||
|
public function setPermissionsForRole(Role $role, array $permissions)
|
||||||
|
{
|
||||||
|
// Update the permissions, filter out null/invalid values
|
||||||
|
$perms = collect($permissions)->filter(static function ($v, $k) {
|
||||||
|
return $v;
|
||||||
|
});
|
||||||
|
|
||||||
|
$role->permissions()->sync($perms);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -48,14 +48,14 @@ class UserService extends Service
|
|||||||
* Register a pilot. Also attaches the initial roles
|
* Register a pilot. Also attaches the initial roles
|
||||||
* required, and then triggers the UserRegistered event
|
* required, and then triggers the UserRegistered event
|
||||||
*
|
*
|
||||||
* @param User $user User model
|
* @param User $user User model
|
||||||
* @param array $groups Additional groups to assign
|
* @param array $roles List of "display_name" of groups to assign
|
||||||
*
|
*
|
||||||
* @throws \Exception
|
* @throws \Exception
|
||||||
*
|
*
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function createUser(User $user, array $groups = null)
|
public function createUser(User $user, array $roles = null)
|
||||||
{
|
{
|
||||||
// Determine if we want to auto accept
|
// Determine if we want to auto accept
|
||||||
if (setting('pilots.auto_accept') === true) {
|
if (setting('pilots.auto_accept') === true) {
|
||||||
@@ -66,15 +66,10 @@ class UserService extends Service
|
|||||||
|
|
||||||
$user->save();
|
$user->save();
|
||||||
|
|
||||||
// Attach the user roles
|
|
||||||
// $role = Role::where('name', 'user')->first();
|
|
||||||
// $user->attachRole($role);
|
|
||||||
|
|
||||||
// Attach any additional roles
|
// Attach any additional roles
|
||||||
if (!empty($groups) && is_array($groups)) {
|
if (!empty($roles) && is_array($roles)) {
|
||||||
foreach ($groups as $group) {
|
foreach ($roles as $role) {
|
||||||
$role = Role::where('name', $group)->first();
|
$this->addUserToRole($user, $role);
|
||||||
$user->attachRole($role);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,6 +82,32 @@ class UserService extends Service
|
|||||||
return $user;
|
return $user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a user to a given role
|
||||||
|
*
|
||||||
|
* @param User $user
|
||||||
|
* @param string $roleName
|
||||||
|
*
|
||||||
|
* @return User
|
||||||
|
*/
|
||||||
|
public function addUserToRole(User $user, $roleName): User
|
||||||
|
{
|
||||||
|
$role = Role::where('name', $roleName)->first();
|
||||||
|
$user->attachRole($role);
|
||||||
|
|
||||||
|
return $user;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find and return the next available pilot ID (usually just the max+1)
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getNextAvailablePilotId(): int
|
||||||
|
{
|
||||||
|
return (int) User::max('pilot_id') + 1;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find the next available pilot ID and set the current user's pilot_id to that +1
|
* Find the next available pilot ID and set the current user's pilot_id to that +1
|
||||||
* Called from UserObserver right now after a record is created
|
* Called from UserObserver right now after a record is created
|
||||||
@@ -101,8 +122,7 @@ class UserService extends Service
|
|||||||
return $user;
|
return $user;
|
||||||
}
|
}
|
||||||
|
|
||||||
$max = (int) User::max('pilot_id');
|
$user->pilot_id = $this->getNextAvailablePilotId();
|
||||||
$user->pilot_id = $max + 1;
|
|
||||||
$user->save();
|
$user->save();
|
||||||
|
|
||||||
Log::info('Set pilot ID for user '.$user->id.' to '.$user->pilot_id);
|
Log::info('Set pilot ID for user '.$user->id.' to '.$user->pilot_id);
|
||||||
@@ -348,8 +368,8 @@ class UserService extends Service
|
|||||||
'state' => PirepState::ACCEPTED,
|
'state' => PirepState::ACCEPTED,
|
||||||
];
|
];
|
||||||
|
|
||||||
$flight_count = Pirep::where($w)->count();
|
$pirep_count = Pirep::where($w)->count();
|
||||||
$user->flights = $flight_count;
|
$user->flights = $pirep_count;
|
||||||
|
|
||||||
$flight_time = Pirep::where($w)->sum('flight_time');
|
$flight_time = Pirep::where($w)->sum('flight_time');
|
||||||
$user->flight_time = $flight_time;
|
$user->flight_time = $flight_time;
|
||||||
@@ -359,7 +379,7 @@ class UserService extends Service
|
|||||||
// Recalc the rank
|
// Recalc the rank
|
||||||
$this->calculatePilotRank($user);
|
$this->calculatePilotRank($user);
|
||||||
|
|
||||||
Log::info('User '.$user->ident.' updated; flight count='.$flight_count
|
Log::info('User '.$user->ident.' updated; pirep count='.$pirep_count
|
||||||
.', rank='.$user->rank->name
|
.', rank='.$user->rank->name
|
||||||
.', flight_time='.$user->flight_time.' minutes');
|
.', flight_time='.$user->flight_time.' minutes');
|
||||||
|
|
||||||
|
|||||||
27
app/Support/Utils.php
Normal file
27
app/Support/Utils.php
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Support;
|
||||||
|
|
||||||
|
use Nwidart\Modules\Facades\Module;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Global utilities
|
||||||
|
*/
|
||||||
|
class Utils
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Is the installer enabled?
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function installerEnabled()
|
||||||
|
{
|
||||||
|
/** @var \Nwidart\Modules\Module $installer */
|
||||||
|
$installer = Module::find('installer');
|
||||||
|
if (!$installer) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $installer->isEnabled();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -37,7 +37,7 @@
|
|||||||
"markrogoyski/math-php": "^0.38.0",
|
"markrogoyski/math-php": "^0.38.0",
|
||||||
"myclabs/deep-copy": "~1.9.0",
|
"myclabs/deep-copy": "~1.9.0",
|
||||||
"nabeel/vacentral": "~2.0",
|
"nabeel/vacentral": "~2.0",
|
||||||
"nwidart/laravel-modules": "~5.1",
|
"nwidart/laravel-modules": "^6.0",
|
||||||
"php-units-of-measure/php-units-of-measure": "~2.1.0",
|
"php-units-of-measure/php-units-of-measure": "~2.1.0",
|
||||||
"pragmarx/version": "0.2.*",
|
"pragmarx/version": "0.2.*",
|
||||||
"prettus/l5-repository": "~2.6.0",
|
"prettus/l5-repository": "~2.6.0",
|
||||||
|
|||||||
839
composer.lock
generated
839
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use Nwidart\Modules\Activators\FileActivator;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'namespace' => 'Modules',
|
'namespace' => 'Modules',
|
||||||
'stubs' => [
|
'stubs' => [
|
||||||
@@ -133,4 +135,14 @@ return [
|
|||||||
'register' => [
|
'register' => [
|
||||||
'translations' => true,
|
'translations' => true,
|
||||||
],
|
],
|
||||||
|
|
||||||
|
'activator' => 'file',
|
||||||
|
'activators' => [
|
||||||
|
'file' => [
|
||||||
|
'class' => FileActivator::class,
|
||||||
|
'statuses-file' => config_path('modules_statuses.json'),
|
||||||
|
'cache-key' => 'activator.installed',
|
||||||
|
'cache-lifetime' => 604800,
|
||||||
|
],
|
||||||
|
],
|
||||||
];
|
];
|
||||||
|
|||||||
7
config/modules_statuses.json
Normal file
7
config/modules_statuses.json
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"Awards": true,
|
||||||
|
"Installer": true,
|
||||||
|
"Sample": true,
|
||||||
|
"VMSAcars": true,
|
||||||
|
"Vacentral": true
|
||||||
|
}
|
||||||
@@ -14,7 +14,7 @@ return [
|
|||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'default' => env('QUEUE_DRIVER', 'sync'),
|
'default' => env('QUEUE_DRIVER', 'database'),
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
return [
|
return [
|
||||||
'pagination' => [
|
'pagination' => [
|
||||||
'limit' => 50,
|
'limit' => 20,
|
||||||
],
|
],
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -1,16 +1,15 @@
|
|||||||
<code_scheme name="Laravel" version="173">
|
<code_scheme name="phpVMS" version="173">
|
||||||
<option name="OTHER_INDENT_OPTIONS">
|
|
||||||
<value>
|
|
||||||
<option name="USE_TAB_CHARACTER" value="true" />
|
|
||||||
</value>
|
|
||||||
</option>
|
|
||||||
<PHPCodeStyleSettings>
|
<PHPCodeStyleSettings>
|
||||||
<option name="ALIGN_KEY_VALUE_PAIRS" value="true" />
|
<option name="ALIGN_KEY_VALUE_PAIRS" value="true" />
|
||||||
<option name="ALIGN_PHPDOC_PARAM_NAMES" value="true" />
|
<option name="ALIGN_PHPDOC_PARAM_NAMES" value="true" />
|
||||||
<option name="ALIGN_PHPDOC_COMMENTS" value="true" />
|
<option name="ALIGN_PHPDOC_COMMENTS" value="true" />
|
||||||
<option name="CONCAT_SPACES" value="false" />
|
<option name="CONCAT_SPACES" value="false" />
|
||||||
<option name="COMMA_AFTER_LAST_ARRAY_ELEMENT" value="true" />
|
<option name="COMMA_AFTER_LAST_ARRAY_ELEMENT" value="true" />
|
||||||
<option name="PHPDOC_KEEP_BLANK_LINES" value="false" />
|
<option name="PHPDOC_BLANK_LINE_BEFORE_TAGS" value="true" />
|
||||||
|
<option name="PHPDOC_BLANK_LINES_AROUND_PARAMETERS" value="true" />
|
||||||
|
<option name="PHPDOC_WRAP_LONG_LINES" value="true" />
|
||||||
|
<option name="THROWS_WEIGHT" value="1" />
|
||||||
|
<option name="RETURN_WEIGHT" value="2" />
|
||||||
<option name="LOWER_CASE_BOOLEAN_CONST" value="true" />
|
<option name="LOWER_CASE_BOOLEAN_CONST" value="true" />
|
||||||
<option name="LOWER_CASE_NULL_CONST" value="true" />
|
<option name="LOWER_CASE_NULL_CONST" value="true" />
|
||||||
<option name="ELSE_IF_STYLE" value="COMBINE" />
|
<option name="ELSE_IF_STYLE" value="COMBINE" />
|
||||||
@@ -21,11 +20,17 @@
|
|||||||
<option name="SPACE_AFTER_UNARY_NOT" value="true" />
|
<option name="SPACE_AFTER_UNARY_NOT" value="true" />
|
||||||
<option name="SPACES_WITHIN_SHORT_ECHO_TAGS" value="false" />
|
<option name="SPACES_WITHIN_SHORT_ECHO_TAGS" value="false" />
|
||||||
<option name="FORCE_SHORT_DECLARATION_ARRAY_STYLE" value="true" />
|
<option name="FORCE_SHORT_DECLARATION_ARRAY_STYLE" value="true" />
|
||||||
<option name="PHPDOC_USE_FQCN" value="true" />
|
|
||||||
</PHPCodeStyleSettings>
|
</PHPCodeStyleSettings>
|
||||||
<XML>
|
<XML>
|
||||||
<option name="XML_LEGACY_SETTINGS_IMPORTED" value="true" />
|
<option name="XML_LEGACY_SETTINGS_IMPORTED" value="true" />
|
||||||
</XML>
|
</XML>
|
||||||
|
<codeStyleSettings language="JavaScript">
|
||||||
|
<indentOptions>
|
||||||
|
<option name="INDENT_SIZE" value="2" />
|
||||||
|
<option name="CONTINUATION_INDENT_SIZE" value="2" />
|
||||||
|
<option name="TAB_SIZE" value="2" />
|
||||||
|
</indentOptions>
|
||||||
|
</codeStyleSettings>
|
||||||
<codeStyleSettings language="PHP">
|
<codeStyleSettings language="PHP">
|
||||||
<option name="KEEP_LINE_BREAKS" value="false" />
|
<option name="KEEP_LINE_BREAKS" value="false" />
|
||||||
<option name="KEEP_FIRST_COLUMN_COMMENT" value="false" />
|
<option name="KEEP_FIRST_COLUMN_COMMENT" value="false" />
|
||||||
|
|||||||
1
modules/.gitignore
vendored
1
modules/.gitignore
vendored
@@ -4,6 +4,7 @@
|
|||||||
/*/
|
/*/
|
||||||
!.gitignore
|
!.gitignore
|
||||||
!/Awards
|
!/Awards
|
||||||
|
!/Importer
|
||||||
!/Installer
|
!/Installer
|
||||||
!/Sample
|
!/Sample
|
||||||
!/Vacentral
|
!/Vacentral
|
||||||
|
|||||||
9
modules/Awards/Providers/AwardServiceProvider.php
Normal file
9
modules/Awards/Providers/AwardServiceProvider.php
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Awards\Providers;
|
||||||
|
|
||||||
|
use Illuminate\Support\ServiceProvider;
|
||||||
|
|
||||||
|
class AwardServiceProvider extends ServiceProvider
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -5,7 +5,9 @@
|
|||||||
"keywords": [],
|
"keywords": [],
|
||||||
"active": 1,
|
"active": 1,
|
||||||
"order": 0,
|
"order": 0,
|
||||||
"providers": [],
|
"providers": [
|
||||||
|
"Modules\\Awards\\Providers\\AwardServiceProvider"
|
||||||
|
],
|
||||||
"aliases": {},
|
"aliases": {},
|
||||||
"files": [],
|
"files": [],
|
||||||
"requires": []
|
"requires": []
|
||||||
|
|||||||
@@ -1,5 +1,12 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use Modules\Installer\Services\Importer\Stages\Stage1;
|
||||||
|
use Modules\Installer\Services\Importer\Stages\Stage2;
|
||||||
|
use Modules\Installer\Services\Importer\Stages\Stage3;
|
||||||
|
use Modules\Installer\Services\Importer\Stages\Stage4;
|
||||||
|
use Modules\Installer\Services\Importer\Stages\Stage5;
|
||||||
|
use Modules\Installer\Services\Importer\Stages\Stage6;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'php' => [
|
'php' => [
|
||||||
'version' => '7.2',
|
'version' => '7.2',
|
||||||
@@ -37,4 +44,16 @@ return [
|
|||||||
'storage/framework/views',
|
'storage/framework/views',
|
||||||
'storage/logs',
|
'storage/logs',
|
||||||
],
|
],
|
||||||
|
|
||||||
|
'importer' => [
|
||||||
|
'batch_size' => 150,
|
||||||
|
'stages' => [
|
||||||
|
'stage1' => Stage1::class,
|
||||||
|
'stage2' => Stage2::class,
|
||||||
|
'stage3' => Stage3::class,
|
||||||
|
'stage4' => Stage4::class,
|
||||||
|
'stage5' => Stage5::class,
|
||||||
|
'stage6' => Stage6::class,
|
||||||
|
],
|
||||||
|
],
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Installer\Console\Commands;
|
||||||
|
|
||||||
|
use App\Contracts\Command;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Modules\Installer\Exceptions\ImporterNextRecordSet;
|
||||||
|
use Modules\Installer\Exceptions\StageCompleted;
|
||||||
|
use Modules\Installer\Services\Importer\ImporterService;
|
||||||
|
|
||||||
|
class ImportFromClassicCommand extends Command
|
||||||
|
{
|
||||||
|
protected $signature = 'phpvms:importer {db_host} {db_name} {db_user} {db_pass?} {table_prefix=phpvms_}';
|
||||||
|
protected $description = 'Import from an older version of phpVMS';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run dev related commands
|
||||||
|
*/
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
$creds = [
|
||||||
|
'host' => $this->argument('db_host'),
|
||||||
|
'name' => $this->argument('db_name'),
|
||||||
|
'user' => $this->argument('db_user'),
|
||||||
|
'pass' => $this->argument('db_pass'),
|
||||||
|
'table_prefix' => $this->argument('table_prefix'),
|
||||||
|
];
|
||||||
|
|
||||||
|
$importerSvc = new ImporterService();
|
||||||
|
|
||||||
|
$importerSvc->saveCredentials($creds);
|
||||||
|
|
||||||
|
$stage = 'stage1';
|
||||||
|
$start = 0;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
$importerSvc->run($stage, $start);
|
||||||
|
} catch (ImporterNextRecordSet $e) {
|
||||||
|
Log::info('More records, starting from '.$e->nextOffset);
|
||||||
|
$start = $e->nextOffset;
|
||||||
|
} catch (StageCompleted $e) {
|
||||||
|
$stage = $e->nextStage;
|
||||||
|
$start = 0;
|
||||||
|
|
||||||
|
Log::info('Stage '.$stage.' completed, moving to '.$e->nextStage);
|
||||||
|
if ($e->nextStage === 'complete') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
22
modules/Installer/Exceptions/ImporterNextRecordSet.php
Normal file
22
modules/Installer/Exceptions/ImporterNextRecordSet.php
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Installer\Exceptions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Go to the next page of the importer
|
||||||
|
*/
|
||||||
|
class ImporterNextRecordSet extends \Exception
|
||||||
|
{
|
||||||
|
public $nextOffset;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ImporterNextRecordSet constructor.
|
||||||
|
*
|
||||||
|
* @param int $nextOffset Where to start the next set of reads from
|
||||||
|
*/
|
||||||
|
public function __construct($nextOffset)
|
||||||
|
{
|
||||||
|
parent::__construct('', 0, null);
|
||||||
|
$this->nextOffset = $nextOffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
11
modules/Installer/Exceptions/ImporterNoMoreRecords.php
Normal file
11
modules/Installer/Exceptions/ImporterNoMoreRecords.php
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Installer\Exceptions;
|
||||||
|
|
||||||
|
class ImporterNoMoreRecords extends \Exception
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
parent::__construct('', 0, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
17
modules/Installer/Exceptions/StageCompleted.php
Normal file
17
modules/Installer/Exceptions/StageCompleted.php
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Installer\Exceptions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signals that the stage is completed and we should go to the next one
|
||||||
|
*/
|
||||||
|
class StageCompleted extends \Exception
|
||||||
|
{
|
||||||
|
public $nextStage;
|
||||||
|
|
||||||
|
public function __construct($nextStage)
|
||||||
|
{
|
||||||
|
$this->nextStage = $nextStage;
|
||||||
|
parent::__construct('', 0, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
87
modules/Installer/Http/Controllers/ImporterController.php
Normal file
87
modules/Installer/Http/Controllers/ImporterController.php
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Installer\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Contracts\Controller;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Modules\Installer\Exceptions\ImporterNextRecordSet;
|
||||||
|
use Modules\Installer\Exceptions\StageCompleted;
|
||||||
|
use Modules\Installer\Services\Importer\ImporterService;
|
||||||
|
|
||||||
|
class ImporterController extends Controller
|
||||||
|
{
|
||||||
|
private $importerSvc;
|
||||||
|
|
||||||
|
public function __construct(ImporterService $importerSvc)
|
||||||
|
{
|
||||||
|
$this->importerSvc = $importerSvc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the main page for the importer; show form for the admin email
|
||||||
|
* and the credentials for the other database
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||||
|
*/
|
||||||
|
public function index(Request $request)
|
||||||
|
{
|
||||||
|
return view('installer::importer/step1-configure');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The post from the above
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||||
|
*/
|
||||||
|
public function config(Request $request)
|
||||||
|
{
|
||||||
|
// Save the credentials to use later
|
||||||
|
$this->importerSvc->saveCredentialsFromRequest($request);
|
||||||
|
|
||||||
|
// Send it to run, step1
|
||||||
|
return redirect(route('importer.run').'?stage=stage1&start=0');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the importer. Pass in query string with a few different parameters:
|
||||||
|
*
|
||||||
|
* stage=STAGE NAME
|
||||||
|
* start=record_start
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||||
|
*/
|
||||||
|
public function run(Request $request)
|
||||||
|
{
|
||||||
|
$stage = $request->get('stage');
|
||||||
|
$start = $request->get('start');
|
||||||
|
|
||||||
|
Log::info('Starting stage '.$stage.' from offset '.$start);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$this->importerSvc->run($stage, $start);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The importer wants to move onto the next set of records, so refresh this page and continue
|
||||||
|
catch (ImporterNextRecordSet $e) {
|
||||||
|
Log::info('Getting more records for stage '.$stage.', starting at '.$e->nextOffset);
|
||||||
|
return redirect(route('importer.run').'?stage='.$stage.'&start='.$e->nextOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This stage is completed, so move onto the next one
|
||||||
|
catch (StageCompleted $e) {
|
||||||
|
if ($e->nextStage === 'complete') {
|
||||||
|
return view('installer::importer/complete');
|
||||||
|
}
|
||||||
|
|
||||||
|
Log::info('Completed stage '.$stage.', redirect to '.$e->nextStage);
|
||||||
|
return redirect(route('importer.run').'?stage='.$e->nextStage.'&start=0');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,9 +21,6 @@ use Modules\Installer\Services\DatabaseService;
|
|||||||
use Modules\Installer\Services\RequirementsService;
|
use Modules\Installer\Services\RequirementsService;
|
||||||
use Symfony\Component\HttpFoundation\File\Exception\FileException;
|
use Symfony\Component\HttpFoundation\File\Exception\FileException;
|
||||||
|
|
||||||
/**
|
|
||||||
* Class InstallerController
|
|
||||||
*/
|
|
||||||
class InstallerController extends Controller
|
class InstallerController extends Controller
|
||||||
{
|
{
|
||||||
private $airlineRepo;
|
private $airlineRepo;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use App\Services\Installer\MigrationService;
|
|||||||
use App\Services\Installer\SeederService;
|
use App\Services\Installer\SeederService;
|
||||||
use function count;
|
use function count;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class UpdaterController
|
* Class UpdaterController
|
||||||
|
|||||||
9
modules/Installer/Http/Routes/importer.php
Normal file
9
modules/Installer/Http/Routes/importer.php
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Route;
|
||||||
|
|
||||||
|
Route::get('/', 'ImporterController@index')->name('index');
|
||||||
|
Route::post('/config', 'ImporterController@config')->name('config');
|
||||||
|
Route::get('/run', 'ImporterController@run')->name('run');
|
||||||
|
|
||||||
|
Route::get('/complete', 'ImporterController@complete')->name('complete');
|
||||||
@@ -3,8 +3,9 @@
|
|||||||
namespace Modules\Installer\Providers;
|
namespace Modules\Installer\Providers;
|
||||||
|
|
||||||
use App\Services\ModuleService;
|
use App\Services\ModuleService;
|
||||||
|
use Illuminate\Support\Facades\Route;
|
||||||
use Illuminate\Support\ServiceProvider;
|
use Illuminate\Support\ServiceProvider;
|
||||||
use Route;
|
use Modules\Installer\Console\Commands\ImportFromClassicCommand;
|
||||||
|
|
||||||
class InstallerServiceProvider extends ServiceProvider
|
class InstallerServiceProvider extends ServiceProvider
|
||||||
{
|
{
|
||||||
@@ -17,6 +18,7 @@ class InstallerServiceProvider extends ServiceProvider
|
|||||||
{
|
{
|
||||||
$this->moduleSvc = app(ModuleService::class);
|
$this->moduleSvc = app(ModuleService::class);
|
||||||
|
|
||||||
|
$this->registerCommands();
|
||||||
$this->registerRoutes();
|
$this->registerRoutes();
|
||||||
$this->registerTranslations();
|
$this->registerTranslations();
|
||||||
$this->registerConfig();
|
$this->registerConfig();
|
||||||
@@ -25,6 +27,13 @@ class InstallerServiceProvider extends ServiceProvider
|
|||||||
$this->loadMigrationsFrom(__DIR__.'/../Database/migrations');
|
$this->loadMigrationsFrom(__DIR__.'/../Database/migrations');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function registerCommands()
|
||||||
|
{
|
||||||
|
$this->commands([
|
||||||
|
ImportFromClassicCommand::class,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register the routes
|
* Register the routes
|
||||||
*/
|
*/
|
||||||
@@ -47,6 +56,15 @@ class InstallerServiceProvider extends ServiceProvider
|
|||||||
], function () {
|
], function () {
|
||||||
$this->loadRoutesFrom(__DIR__.'/../Http/Routes/update.php');
|
$this->loadRoutesFrom(__DIR__.'/../Http/Routes/update.php');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Route::group([
|
||||||
|
'as' => 'importer.',
|
||||||
|
'prefix' => 'importer',
|
||||||
|
'middleware' => ['web'],
|
||||||
|
'namespace' => 'Modules\Installer\Http\Controllers',
|
||||||
|
], function () {
|
||||||
|
$this->loadRoutesFrom(__DIR__.'/../Http/Routes/importer.php');
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
@extends('installer::app')
|
||||||
|
@section('title', 'Import Completed!')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<div style="align-content: center;">
|
||||||
|
{{ Form::open(['route' => 'installer.complete', 'method' => 'GET']) }}
|
||||||
|
|
||||||
|
<h4>Installer Completed!</h4>
|
||||||
|
|
||||||
|
<p>Edit the <span class="code">config.php</span> to fill in some additional settings. </p>
|
||||||
|
<p>Click the button to proceed to the login screen!</p>
|
||||||
|
|
||||||
|
<p style="text-align: right">
|
||||||
|
{{ Form::submit('Install Complete! Continue to Log-In >>',
|
||||||
|
['class' => 'btn btn-success'])
|
||||||
|
}}
|
||||||
|
</p>
|
||||||
|
{{ Form::close() }}
|
||||||
|
</div>
|
||||||
|
@endsection
|
||||||
@@ -0,0 +1,134 @@
|
|||||||
|
@extends('installer::app')
|
||||||
|
@section('title', 'Import Configuration')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<div style="align-content: center;">
|
||||||
|
{{ Form::open(['route' => 'importer.config', 'method' => 'POST']) }}
|
||||||
|
<table class="table" width="25%">
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<h4>IMPORTANT NOTES</h4>
|
||||||
|
<ul>
|
||||||
|
<li>If you have more than 1000 PIREPs or flights, it's best to use the command-line importer!
|
||||||
|
<a href="http://docs.phpvms.net/setup/importing-from-v2-v5" target="_blank">Click here</a> to
|
||||||
|
see the documentation of how to use it.</li>
|
||||||
|
<li><strong>THIS WILL WIPE OUT YOUR EXISTING DATA</strong> - this is required to make sure that things like
|
||||||
|
pilot IDs match up</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td colspan="2"><h4>Site Config</h4></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>Admin Email</td>
|
||||||
|
<td style="text-align:center;">
|
||||||
|
<div class="form-group">
|
||||||
|
{{ Form::input('text', 'email', '', ['class' => 'form-control']) }}
|
||||||
|
<p>The admin's email address, the password for this will be reset</p>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td colspan="2"><h4>Database Config</h4></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tbody id="mysql_settings">
|
||||||
|
<tr>
|
||||||
|
<td>Database Host</td>
|
||||||
|
<td style="text-align:center;">
|
||||||
|
<div class="form-group">
|
||||||
|
{{ Form::input('text', 'db_host', '127.0.0.1', ['class' => 'form-control']) }}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>Database Port</td>
|
||||||
|
<td style="text-align:center;">
|
||||||
|
<div class="form-group">
|
||||||
|
{{ Form::input('text', 'db_port', '3306', ['class' => 'form-control']) }}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>Database Name</td>
|
||||||
|
<td style="text-align:center;">
|
||||||
|
<div class="form-group">
|
||||||
|
{{ Form::input('text', 'db_name', 'phpvms', ['class' => 'form-control']) }}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>Database User</td>
|
||||||
|
<td style="text-align:center;">
|
||||||
|
<div class="form-group">
|
||||||
|
{{ Form::input('text', 'db_user', null, ['class' => 'form-control']) }}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>Database Password</td>
|
||||||
|
<td style="text-align:center;">
|
||||||
|
<div class="form-group">
|
||||||
|
{{ Form::input('text', 'db_pass', null, ['class' => 'form-control']) }}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td colspan="2" style="text-align: right;">
|
||||||
|
{{ Form::submit('Test Database Credentials', ['class' => 'btn btn-info', 'id' => 'dbtest_button']) }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>Database Prefix</td>
|
||||||
|
<td style="text-align:center;">
|
||||||
|
<div class="form-group">
|
||||||
|
{{ Form::input('text', 'db_prefix', 'phpvms_', ['class' => 'form-control']) }}
|
||||||
|
<p>Prefix of the tables, if you're using one</p>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
</table>
|
||||||
|
<div id="dbtest"></div>
|
||||||
|
<p style="text-align: right">
|
||||||
|
{{ Form::submit('Start Importer >>', ['class' => 'btn btn-success']) }}
|
||||||
|
</p>
|
||||||
|
{{ Form::close() }}
|
||||||
|
</div>
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
@section('scripts')
|
||||||
|
<script>
|
||||||
|
$(document).ready(() => {
|
||||||
|
|
||||||
|
$("#dbtest_button").click((e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
const opts = {
|
||||||
|
_token: "{{ csrf_token() }}",
|
||||||
|
db_conn: $("#db_conn option:selected").text(),
|
||||||
|
db_host: $("input[name=db_host]").val(),
|
||||||
|
db_port: $("input[name=db_port]").val(),
|
||||||
|
db_name: $("input[name=db_name]").val(),
|
||||||
|
db_user: $("input[name=db_user]").val(),
|
||||||
|
db_pass: $("input[name=db_pass]").val(),
|
||||||
|
};
|
||||||
|
|
||||||
|
$.post("{{ route('installer.dbtest') }}", opts, (data) => {
|
||||||
|
$("#dbtest").html(data);
|
||||||
|
})
|
||||||
|
})
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
@endsection
|
||||||
@@ -7,6 +7,12 @@
|
|||||||
{{ Form::open(['route' => 'installer.usersetup', 'method' => 'POST']) }}
|
{{ Form::open(['route' => 'installer.usersetup', 'method' => 'POST']) }}
|
||||||
<table class="table" width="25%">
|
<table class="table" width="25%">
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td colspan="2" style="text-align: right">
|
||||||
|
<a href="{{ route('importer.index') }}">Importing from a legacy install?</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2"><h4>Airline Information</h4></td>
|
<td colspan="2"><h4>Airline Information</h4></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
78
modules/Installer/Services/Importer/BaseImporter.php
Normal file
78
modules/Installer/Services/Importer/BaseImporter.php
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Installer\Services\Importer;
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Foundation\Bus\Dispatchable;
|
||||||
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
|
use Modules\Installer\Exceptions\ImporterNextRecordSet;
|
||||||
|
use Modules\Installer\Exceptions\ImporterNoMoreRecords;
|
||||||
|
use Modules\Installer\Utils\IdMapper;
|
||||||
|
use Modules\Installer\Utils\ImporterDB;
|
||||||
|
use Modules\Installer\Utils\LoggerTrait;
|
||||||
|
|
||||||
|
abstract class BaseImporter implements ShouldQueue
|
||||||
|
{
|
||||||
|
use LoggerTrait, Dispatchable, InteractsWithQueue, Queueable;
|
||||||
|
|
||||||
|
protected $db;
|
||||||
|
protected $idMapper;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$importerService = app(ImporterService::class);
|
||||||
|
$this->db = new ImporterDB($importerService->getCredentials());
|
||||||
|
$this->idMapper = app(IdMapper::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The start method. Takes the offset to start from
|
||||||
|
*
|
||||||
|
* @param int $start
|
||||||
|
*
|
||||||
|
* @throws ImporterNoMoreRecords
|
||||||
|
* @throws ImporterNextRecordSet
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
abstract public function run($start = 0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $date
|
||||||
|
*
|
||||||
|
* @return Carbon
|
||||||
|
*/
|
||||||
|
protected function parseDate($date)
|
||||||
|
{
|
||||||
|
$carbon = Carbon::parse($date);
|
||||||
|
|
||||||
|
return $carbon;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Take a decimal duration and convert it to minutes
|
||||||
|
*
|
||||||
|
* @param $duration
|
||||||
|
*
|
||||||
|
* @return float|int
|
||||||
|
*/
|
||||||
|
protected function convertDuration($duration)
|
||||||
|
{
|
||||||
|
if (strpos($duration, '.') !== false) {
|
||||||
|
$delim = '.';
|
||||||
|
} elseif (strpos($duration, ':')) {
|
||||||
|
$delim = ':';
|
||||||
|
} else {
|
||||||
|
// no delimiter, assume it's just a straight hour
|
||||||
|
return (int) $duration * 60;
|
||||||
|
}
|
||||||
|
|
||||||
|
$hm = explode($delim, $duration);
|
||||||
|
$hours = (int) $hm[0] * 60;
|
||||||
|
$mins = (int) $hm[1];
|
||||||
|
|
||||||
|
return $hours + $mins;
|
||||||
|
}
|
||||||
|
}
|
||||||
68
modules/Installer/Services/Importer/BaseStage.php
Normal file
68
modules/Installer/Services/Importer/BaseStage.php
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Installer\Services\Importer;
|
||||||
|
|
||||||
|
use App\Repositories\KvpRepository;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Modules\Installer\Exceptions\ImporterNextRecordSet;
|
||||||
|
use Modules\Installer\Exceptions\ImporterNoMoreRecords;
|
||||||
|
use Modules\Installer\Exceptions\StageCompleted;
|
||||||
|
use Modules\Installer\Utils\IdMapper;
|
||||||
|
use Modules\Installer\Utils\ImporterDB;
|
||||||
|
use Modules\Installer\Utils\LoggerTrait;
|
||||||
|
|
||||||
|
class BaseStage
|
||||||
|
{
|
||||||
|
use LoggerTrait;
|
||||||
|
|
||||||
|
public $importers = [];
|
||||||
|
public $nextStage = '';
|
||||||
|
|
||||||
|
protected $db;
|
||||||
|
protected $idMapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var KvpRepository
|
||||||
|
*/
|
||||||
|
protected $kvpRepo;
|
||||||
|
|
||||||
|
public function __construct(ImporterDB $db, IdMapper $mapper)
|
||||||
|
{
|
||||||
|
$this->db = $db;
|
||||||
|
$this->idMapper = $mapper;
|
||||||
|
|
||||||
|
$this->kvpRepo = app(KvpRepository::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run all of the given importers
|
||||||
|
*
|
||||||
|
* @param $start
|
||||||
|
*
|
||||||
|
* @throws ImporterNextRecordSet
|
||||||
|
* @throws StageCompleted
|
||||||
|
*/
|
||||||
|
public function run($start)
|
||||||
|
{
|
||||||
|
$importersRun = $this->kvpRepo->get('importers.run', []);
|
||||||
|
|
||||||
|
foreach ($this->importers as $klass) {
|
||||||
|
/** @var $importer \Modules\Installer\Services\Importer\BaseImporter */
|
||||||
|
$importer = new $klass($this->db, $this->idMapper);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$importer->run($start);
|
||||||
|
} catch (ImporterNextRecordSet $e) {
|
||||||
|
Log::info('Requesting next set of records');
|
||||||
|
|
||||||
|
throw $e;
|
||||||
|
} catch (ImporterNoMoreRecords $e) {
|
||||||
|
$importersRun[] = $importer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->kvpRepo->save('importers.run', $importersRun);
|
||||||
|
|
||||||
|
throw new StageCompleted($this->nextStage);
|
||||||
|
}
|
||||||
|
}
|
||||||
111
modules/Installer/Services/Importer/ImporterService.php
Normal file
111
modules/Installer/Services/Importer/ImporterService.php
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Installer\Services\Importer;
|
||||||
|
|
||||||
|
use App\Contracts\Service;
|
||||||
|
use App\Repositories\KvpRepository;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Modules\Installer\Exceptions\ImporterNextRecordSet;
|
||||||
|
use Modules\Installer\Exceptions\StageCompleted;
|
||||||
|
use Modules\Installer\Utils\IdMapper;
|
||||||
|
use Modules\Installer\Utils\ImporterDB;
|
||||||
|
|
||||||
|
class ImporterService extends Service
|
||||||
|
{
|
||||||
|
private $CREDENTIALS_KEY = 'legacy.importer.db';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var KvpRepository
|
||||||
|
*/
|
||||||
|
private $kvpRepo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hold some of our data on disk for the migration
|
||||||
|
*
|
||||||
|
* @var IdMapper
|
||||||
|
*/
|
||||||
|
private $idMapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hold the PDO connection to the old database
|
||||||
|
*
|
||||||
|
* @var ImporterDB
|
||||||
|
*/
|
||||||
|
private $db;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->idMapper = app(IdMapper::class);
|
||||||
|
$this->kvpRepo = app(KvpRepository::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save the credentials from a request
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
*/
|
||||||
|
public function saveCredentialsFromRequest(Request $request)
|
||||||
|
{
|
||||||
|
$creds = [
|
||||||
|
'admin_email' => $request->post('email'),
|
||||||
|
'host' => $request->post('db_host'),
|
||||||
|
'port' => $request->post('db_port'),
|
||||||
|
'name' => $request->post('db_name'),
|
||||||
|
'user' => $request->post('db_user'),
|
||||||
|
'pass' => $request->post('db_pass'),
|
||||||
|
'table_prefix' => $request->post('db_prefix'),
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->saveCredentials($creds);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save the given credentials
|
||||||
|
*
|
||||||
|
* @param array $creds
|
||||||
|
*/
|
||||||
|
public function saveCredentials(array $creds)
|
||||||
|
{
|
||||||
|
$creds = array_merge([
|
||||||
|
'admin_email' => '',
|
||||||
|
'host' => '',
|
||||||
|
'port' => '',
|
||||||
|
'name' => '',
|
||||||
|
'user' => '',
|
||||||
|
'pass' => 3306,
|
||||||
|
'table_prefix' => 'phpvms_',
|
||||||
|
], $creds);
|
||||||
|
|
||||||
|
$this->kvpRepo->save($this->CREDENTIALS_KEY, $creds);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the saved credentials
|
||||||
|
*/
|
||||||
|
public function getCredentials()
|
||||||
|
{
|
||||||
|
return $this->kvpRepo->get($this->CREDENTIALS_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run a given stage
|
||||||
|
*
|
||||||
|
* @param $stage
|
||||||
|
* @param int $start
|
||||||
|
*
|
||||||
|
* @throws ImporterNextRecordSet
|
||||||
|
* @throws StageCompleted
|
||||||
|
*
|
||||||
|
* @return int|void
|
||||||
|
*/
|
||||||
|
public function run($stage, $start = 0)
|
||||||
|
{
|
||||||
|
$db = new ImporterDB($this->kvpRepo->get($this->CREDENTIALS_KEY));
|
||||||
|
|
||||||
|
$stageKlass = config('installer.importer.stages.'.$stage);
|
||||||
|
|
||||||
|
/** @var $stage \Modules\Installer\Services\Importer\BaseStage */
|
||||||
|
$stage = new $stageKlass($db, $this->idMapper);
|
||||||
|
$stage->run($start);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Installer\Services\Importer\Importers;
|
||||||
|
|
||||||
|
use App\Models\Aircraft;
|
||||||
|
use App\Models\Airline;
|
||||||
|
use App\Models\Subfleet;
|
||||||
|
use Modules\Installer\Exceptions\ImporterNoMoreRecords;
|
||||||
|
use Modules\Installer\Services\Importer\BaseImporter;
|
||||||
|
|
||||||
|
class AircraftImporter extends BaseImporter
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* CONSTANTS
|
||||||
|
*/
|
||||||
|
public const SUBFLEET_NAME = 'Imported Aircraft';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $start
|
||||||
|
*
|
||||||
|
* @throws \Modules\Installer\Exceptions\ImporterNoMoreRecords
|
||||||
|
*/
|
||||||
|
public function run($start = 0)
|
||||||
|
{
|
||||||
|
$this->comment('--- AIRCRAFT IMPORT ---');
|
||||||
|
|
||||||
|
$subfleet = $this->getSubfleet();
|
||||||
|
|
||||||
|
$this->info('Subfleet ID is '.$subfleet->id);
|
||||||
|
|
||||||
|
$count = 0;
|
||||||
|
foreach ($this->db->readRows('aircraft') as $row) {
|
||||||
|
$where = [
|
||||||
|
'name' => $row->fullname,
|
||||||
|
'registration' => $row->registration,
|
||||||
|
];
|
||||||
|
|
||||||
|
$aircraft = Aircraft::firstOrCreate($where, [
|
||||||
|
'icao' => $row->icao,
|
||||||
|
'subfleet_id' => $subfleet->id,
|
||||||
|
'active' => $row->enabled,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->idMapper->addMapping('aircraft', $row->id, $aircraft->id);
|
||||||
|
|
||||||
|
if ($aircraft->wasRecentlyCreated) {
|
||||||
|
$count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->info('Imported '.$count.' aircraft');
|
||||||
|
|
||||||
|
throw new ImporterNoMoreRecords();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the subfleet
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
protected function getSubfleet()
|
||||||
|
{
|
||||||
|
$airline = Airline::first();
|
||||||
|
$subfleet = Subfleet::firstOrCreate([
|
||||||
|
'airline_id' => $airline->id,
|
||||||
|
'name' => self::SUBFLEET_NAME,
|
||||||
|
], ['type' => 'PHPVMS']);
|
||||||
|
|
||||||
|
return $subfleet;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Installer\Services\Importer\Importers;
|
||||||
|
|
||||||
|
use App\Models\Airline;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Modules\Installer\Exceptions\ImporterNoMoreRecords;
|
||||||
|
use Modules\Installer\Services\Importer\BaseImporter;
|
||||||
|
|
||||||
|
class AirlineImporter extends BaseImporter
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param int $start
|
||||||
|
*
|
||||||
|
* @throws \Modules\Installer\Exceptions\ImporterNoMoreRecords
|
||||||
|
*/
|
||||||
|
public function run($start = 0)
|
||||||
|
{
|
||||||
|
$this->comment('--- AIRLINE IMPORT ---');
|
||||||
|
|
||||||
|
$count = 0;
|
||||||
|
foreach ($this->db->readRows('airlines', $start) as $row) {
|
||||||
|
$airline = Airline::firstOrCreate(['icao' => $row->code], [
|
||||||
|
'iata' => $row->code,
|
||||||
|
'name' => $row->name,
|
||||||
|
'active' => $row->enabled,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->idMapper->addMapping('airlines', $row->id, $airline->id);
|
||||||
|
$this->idMapper->addMapping('airlines', $row->code, $airline->id);
|
||||||
|
|
||||||
|
Log::debug('Mapping '.$row->id.'/'.$row->code.' to ID '.$airline->id);
|
||||||
|
|
||||||
|
if ($airline->wasRecentlyCreated) {
|
||||||
|
$count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->info('Imported '.$count.' airlines');
|
||||||
|
|
||||||
|
throw new ImporterNoMoreRecords();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Installer\Services\Importer\Importers;
|
||||||
|
|
||||||
|
use App\Models\Airport;
|
||||||
|
use Modules\Installer\Exceptions\ImporterNoMoreRecords;
|
||||||
|
use Modules\Installer\Services\Importer\BaseImporter;
|
||||||
|
|
||||||
|
class AirportImporter extends BaseImporter
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param int $start
|
||||||
|
*
|
||||||
|
* @throws \Modules\Installer\Exceptions\ImporterNoMoreRecords
|
||||||
|
*/
|
||||||
|
public function run($start = 0)
|
||||||
|
{
|
||||||
|
$this->comment('--- AIRPORT IMPORT ---');
|
||||||
|
|
||||||
|
$count = 0;
|
||||||
|
foreach ($this->db->readRows('airports', $start) as $row) {
|
||||||
|
$attrs = [
|
||||||
|
'id' => trim($row->icao),
|
||||||
|
'icao' => trim($row->icao),
|
||||||
|
'name' => $row->name,
|
||||||
|
'country' => $row->country,
|
||||||
|
'lat' => $row->lat,
|
||||||
|
'lon' => $row->lng,
|
||||||
|
'hub' => $row->hub,
|
||||||
|
];
|
||||||
|
|
||||||
|
$airport = Airport::updateOrCreate(['id' => $attrs['id']], $attrs);
|
||||||
|
|
||||||
|
if ($airport->wasRecentlyCreated) {
|
||||||
|
$count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->info('Imported '.$count.' airports');
|
||||||
|
|
||||||
|
throw new ImporterNoMoreRecords();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Installer\Services\Importer\Importers;
|
||||||
|
|
||||||
|
use App\Models\Flight;
|
||||||
|
use Modules\Installer\Services\Importer\BaseImporter;
|
||||||
|
|
||||||
|
class FlightImporter extends BaseImporter
|
||||||
|
{
|
||||||
|
public function run($start = 0)
|
||||||
|
{
|
||||||
|
$this->comment('--- FLIGHT SCHEDULE IMPORT ---');
|
||||||
|
|
||||||
|
$count = 0;
|
||||||
|
foreach ($this->db->readRows('schedules', $start) as $row) {
|
||||||
|
$airline_id = $this->idMapper->getMapping('airlines', $row->code);
|
||||||
|
|
||||||
|
$flight_num = trim($row->flightnum);
|
||||||
|
|
||||||
|
$attrs = [
|
||||||
|
'dpt_airport_id' => $row->depicao,
|
||||||
|
'arr_airport_id' => $row->arricao,
|
||||||
|
'route' => $row->route ?: '',
|
||||||
|
'distance' => round($row->distance ?: 0, 2),
|
||||||
|
'level' => $row->flightlevel ?: 0,
|
||||||
|
'dpt_time' => $row->deptime ?: '',
|
||||||
|
'arr_time' => $row->arrtime ?: '',
|
||||||
|
'flight_time' => $this->convertDuration($row->flighttime) ?: '',
|
||||||
|
'notes' => $row->notes ?: '',
|
||||||
|
'active' => $row->enabled ?: true,
|
||||||
|
];
|
||||||
|
|
||||||
|
try {
|
||||||
|
$w = ['airline_id' => $airline_id, 'flight_number' => $flight_num];
|
||||||
|
$flight = Flight::updateOrCreate($w, $attrs);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
//$this->error($e);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->idMapper->addMapping('flights', $row->id, $flight->id);
|
||||||
|
|
||||||
|
// TODO: deserialize route_details into ACARS table
|
||||||
|
|
||||||
|
if ($flight->wasRecentlyCreated) {
|
||||||
|
$count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->info('Imported '.$count.' flights');
|
||||||
|
}
|
||||||
|
}
|
||||||
100
modules/Installer/Services/Importer/Importers/GroupImporter.php
Normal file
100
modules/Installer/Services/Importer/Importers/GroupImporter.php
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Installer\Services\Importer\Importers;
|
||||||
|
|
||||||
|
use App\Models\Role;
|
||||||
|
use App\Services\RoleService;
|
||||||
|
use Modules\Installer\Services\Importer\BaseImporter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Imports the groups into the permissions feature(s)
|
||||||
|
*/
|
||||||
|
class GroupImporter extends BaseImporter
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Permissions in the legacy system, mapping them to the current system
|
||||||
|
*/
|
||||||
|
protected $legacy_permission_set = [
|
||||||
|
'EDIT_NEWS' => 0x1,
|
||||||
|
'EDIT_PAGES' => 0x2,
|
||||||
|
'EDIT_DOWNLOADS' => 0x4,
|
||||||
|
'EMAIL_PILOTS' => 0x8,
|
||||||
|
'EDIT_AIRLINES' => 0x10, //
|
||||||
|
'EDIT_FLEET' => 0x20, //
|
||||||
|
'EDIT_SCHEDULES' => 0x80, //
|
||||||
|
'IMPORT_SCHEDULES' => 0x100, //
|
||||||
|
'MODERATE_REGISTRATIONS' => 0x200,
|
||||||
|
'EDIT_PILOTS' => 0x400, //
|
||||||
|
'EDIT_GROUPS' => 0x800,
|
||||||
|
'EDIT_RANKS' => 0x1000, //
|
||||||
|
'EDIT_AWARDS' => 0x2000, //
|
||||||
|
'MODERATE_PIREPS' => 0x4000, //
|
||||||
|
'VIEW_FINANCES' => 0x8000, //
|
||||||
|
'EDIT_EXPENSES' => 0x10000, //
|
||||||
|
'EDIT_SETTINGS' => 0x20000, //
|
||||||
|
'EDIT_PIREPS_FIELDS' => 0x40000, //
|
||||||
|
'EDIT_PROFILE_FIELDS' => 0x80000, //
|
||||||
|
'EDIT_VACENTRAL' => 0x100000,
|
||||||
|
'ACCESS_ADMIN' => 0x2000000,
|
||||||
|
'FULL_ADMIN' => 35651519, //
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map a legacy value over to one of the current permission values
|
||||||
|
*/
|
||||||
|
protected $legacy_to_permission = [
|
||||||
|
'FULL_ADMIN' => 'admin',
|
||||||
|
'EDIT_AIRLINES' => 'airlines',
|
||||||
|
'EDIT_AWARDS' => 'awards',
|
||||||
|
'EDIT_FLEET' => 'fleet',
|
||||||
|
'EDIT_EXPENCES' => 'finances',
|
||||||
|
'VIEW_FINANCES' => 'finances',
|
||||||
|
'EDIT_SCHEDULES' => 'flights',
|
||||||
|
'EDIT_PILOTS' => 'users',
|
||||||
|
'EDIT_PROFILE_FIELDS' => 'users',
|
||||||
|
'EDIT_SETTINGS' => 'settings',
|
||||||
|
'MODERATE_PIREPS' => 'pireps',
|
||||||
|
'EDIT_PIREPS_FIELDS' => 'pireps',
|
||||||
|
'EDIT_RANKS' => 'ranks',
|
||||||
|
'MODERATE_REGISTRATIONS' => 'users',
|
||||||
|
];
|
||||||
|
|
||||||
|
public function run($start = 0)
|
||||||
|
{
|
||||||
|
$this->comment('--- ROLES/GROUPS IMPORT ---');
|
||||||
|
|
||||||
|
$roleSvc = app(RoleService::class);
|
||||||
|
|
||||||
|
$count = 0;
|
||||||
|
foreach ($this->db->readRows('groups') as $row) {
|
||||||
|
$name = str_slug($row->name);
|
||||||
|
$role = Role::firstOrCreate(
|
||||||
|
['name' => $name],
|
||||||
|
['display_name' => $row->name]
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->idMapper->addMapping('group', $row->groupid, $role->id);
|
||||||
|
|
||||||
|
// See if the permission set mask contains one of the mappings above
|
||||||
|
// Add all of the ones which apply, and then set them on the new role
|
||||||
|
$permissions = [];
|
||||||
|
foreach ($this->legacy_permission_set as $legacy_name => $mask) {
|
||||||
|
if (($row->permissions & $mask) === true) {
|
||||||
|
if (!array_key_exists($legacy_name, $this->legacy_to_permission)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$permissions[] = $this->legacy_to_permission[$legacy_name];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$roleSvc->setPermissionsForRole($role, $permissions);
|
||||||
|
|
||||||
|
if ($role->wasRecentlyCreated) {
|
||||||
|
$count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->info('Imported '.$count.' ranks');
|
||||||
|
}
|
||||||
|
}
|
||||||
122
modules/Installer/Services/Importer/Importers/PirepImporter.php
Normal file
122
modules/Installer/Services/Importer/Importers/PirepImporter.php
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Installer\Services\Importer\Importers;
|
||||||
|
|
||||||
|
use App\Models\Enums\FlightType;
|
||||||
|
use App\Models\Enums\PirepSource;
|
||||||
|
use App\Models\Enums\PirepState;
|
||||||
|
use App\Models\Pirep;
|
||||||
|
use Modules\Installer\Services\Importer\BaseImporter;
|
||||||
|
|
||||||
|
class PirepImporter extends BaseImporter
|
||||||
|
{
|
||||||
|
public function run($start = 0)
|
||||||
|
{
|
||||||
|
$this->comment('--- PIREP IMPORT ---');
|
||||||
|
|
||||||
|
$count = 0;
|
||||||
|
foreach ($this->db->readRows('pireps', $start) as $row) {
|
||||||
|
$pirep_id = $row->pirepid;
|
||||||
|
$user_id = $this->idMapper->getMapping('users', $row->pilotid);
|
||||||
|
$airline_id = $this->idMapper->getMapping('airlines', $row->code);
|
||||||
|
$aircraft_id = $this->idMapper->getMapping('aircraft', $row->aircraft);
|
||||||
|
|
||||||
|
$attrs = [
|
||||||
|
'user_id' => $user_id,
|
||||||
|
'airline_id' => $airline_id,
|
||||||
|
'aircraft_id' => $aircraft_id,
|
||||||
|
'flight_number' => $row->flightnum ?: '',
|
||||||
|
'dpt_airport_id' => $row->depicao,
|
||||||
|
'arr_airport_id' => $row->arricao,
|
||||||
|
'block_fuel' => $row->fuelused,
|
||||||
|
'route' => $row->route ?: '',
|
||||||
|
'source_name' => $row->source,
|
||||||
|
'state' => $this->mapState($row->accepted),
|
||||||
|
'created_at' => $this->parseDate($row->submitdate),
|
||||||
|
'updated_at' => $this->parseDate($row->submitdate),
|
||||||
|
];
|
||||||
|
|
||||||
|
// Set the distance
|
||||||
|
$distance = round($row->distance ?: 0, 2);
|
||||||
|
$attrs['distance'] = $distance;
|
||||||
|
$attrs['planned_distance'] = $distance;
|
||||||
|
|
||||||
|
// Set the flight time properly
|
||||||
|
$duration = $this->convertDuration($row->flighttime_stamp);
|
||||||
|
$attrs['flight_time'] = $duration;
|
||||||
|
$attrs['planned_flight_time'] = $duration;
|
||||||
|
|
||||||
|
// Set how it was filed
|
||||||
|
if (strtoupper($row->source) === 'MANUAL') {
|
||||||
|
$attrs['source'] = PirepSource::MANUAL;
|
||||||
|
} else {
|
||||||
|
$attrs['source'] = PirepSource::ACARS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the flight type
|
||||||
|
$row->flighttype = strtoupper($row->flighttype);
|
||||||
|
if ($row->flighttype === 'P') {
|
||||||
|
$attrs['flight_type'] = FlightType::SCHED_PAX;
|
||||||
|
} elseif ($row->flighttype === 'C') {
|
||||||
|
$attrs['flight_type'] = FlightType::SCHED_CARGO;
|
||||||
|
} else {
|
||||||
|
$attrs['flight_type'] = FlightType::CHARTER_PAX_ONLY;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the flight level of the PIREP is set
|
||||||
|
if (property_exists($row, 'flightlevel')) {
|
||||||
|
$attrs['level'] = $row->flightlevel;
|
||||||
|
} else {
|
||||||
|
$attrs['level'] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$pirep = Pirep::updateOrCreate(['id' => $pirep_id], $attrs);
|
||||||
|
|
||||||
|
//Log::debug('pirep oldid='.$pirep_id.', olduserid='.$row->pilotid
|
||||||
|
// .'; new id='.$pirep->id.', user id='.$user_id);
|
||||||
|
|
||||||
|
$source = strtoupper($row->source);
|
||||||
|
if ($source === 'SMARTCARS') {
|
||||||
|
// TODO: Parse smartcars log into the acars table
|
||||||
|
} elseif ($source === 'KACARS') {
|
||||||
|
// TODO: Parse kACARS log into acars table
|
||||||
|
} elseif ($source === 'XACARS') {
|
||||||
|
// TODO: Parse XACARS log into acars table
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Add extra fields in as PIREP fields
|
||||||
|
$this->idMapper->addMapping('pireps', $row->pirepid, $pirep->id);
|
||||||
|
|
||||||
|
if ($pirep->wasRecentlyCreated) {
|
||||||
|
$count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->info('Imported '.$count.' pireps');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map the old status to the current
|
||||||
|
* https://github.com/nabeelio/phpvms_v2/blob/master/core/app.config.php#L450
|
||||||
|
*
|
||||||
|
* @param int $old_state
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
private function mapState($old_state)
|
||||||
|
{
|
||||||
|
$map = [
|
||||||
|
0 => PirepState::PENDING,
|
||||||
|
1 => PirepState::ACCEPTED,
|
||||||
|
2 => PirepState::REJECTED,
|
||||||
|
3 => PirepState::IN_PROGRESS,
|
||||||
|
];
|
||||||
|
|
||||||
|
$old_state = (int) $old_state;
|
||||||
|
if (!in_array($old_state, $map)) {
|
||||||
|
return PirepState::PENDING;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $map[$old_state];
|
||||||
|
}
|
||||||
|
}
|
||||||
31
modules/Installer/Services/Importer/Importers/RankImport.php
Normal file
31
modules/Installer/Services/Importer/Importers/RankImport.php
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Installer\Services\Importer\Importers;
|
||||||
|
|
||||||
|
use App\Models\Rank;
|
||||||
|
use Modules\Installer\Services\Importer\BaseImporter;
|
||||||
|
|
||||||
|
class RankImport extends BaseImporter
|
||||||
|
{
|
||||||
|
public function run($start = 0)
|
||||||
|
{
|
||||||
|
$this->comment('--- RANK IMPORT ---');
|
||||||
|
|
||||||
|
$count = 0;
|
||||||
|
foreach ($this->db->readRows('ranks') as $row) {
|
||||||
|
$rank = Rank::firstOrCreate(['name' => $row->rank], [
|
||||||
|
'image_url' => $row->rankimage,
|
||||||
|
'hours' => $row->minhours,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->idMapper->addMapping('ranks', $row->rankid, $rank->id);
|
||||||
|
$this->idMapper->addMapping('ranks', $row->rank, $rank->id);
|
||||||
|
|
||||||
|
if ($rank->wasRecentlyCreated) {
|
||||||
|
$count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->info('Imported '.$count.' ranks');
|
||||||
|
}
|
||||||
|
}
|
||||||
139
modules/Installer/Services/Importer/Importers/UserImport.php
Normal file
139
modules/Installer/Services/Importer/Importers/UserImport.php
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Installer\Services\Importer\Importers;
|
||||||
|
|
||||||
|
use App\Facades\Utils;
|
||||||
|
use App\Models\Enums\UserState;
|
||||||
|
use App\Models\User;
|
||||||
|
use App\Services\UserService;
|
||||||
|
use Illuminate\Support\Facades\Hash;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
use Modules\Installer\Services\Importer\BaseImporter;
|
||||||
|
|
||||||
|
class UserImport extends BaseImporter
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var UserService
|
||||||
|
*/
|
||||||
|
private $userSvc;
|
||||||
|
|
||||||
|
public function run($start = 0)
|
||||||
|
{
|
||||||
|
$this->comment('--- USER IMPORT ---');
|
||||||
|
|
||||||
|
$this->userSvc = app(UserService::class);
|
||||||
|
|
||||||
|
$count = 0;
|
||||||
|
$first_row = true;
|
||||||
|
foreach ($this->db->readRows('pilots', $start) as $row) {
|
||||||
|
$pilot_id = $row->pilotid; // This isn't their actual ID
|
||||||
|
$name = $row->firstname.' '.$row->lastname;
|
||||||
|
|
||||||
|
// Figure out which airline, etc, they belong to
|
||||||
|
$airline_id = $this->idMapper->getMapping('airlines', $row->code);
|
||||||
|
// Log::info('User airline from '.$row->code.' to ID '.$airline_id);
|
||||||
|
|
||||||
|
$rank_id = $this->idMapper->getMapping('ranks', $row->rank);
|
||||||
|
$state = $this->getUserState($row->retired);
|
||||||
|
|
||||||
|
if ($first_row) {
|
||||||
|
$new_password = 'admin';
|
||||||
|
$first_row = false;
|
||||||
|
} else {
|
||||||
|
$new_password = Str::random(60);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Look for a user with that pilot ID already. If someone has it
|
||||||
|
if ($this->userSvc->isPilotIdAlreadyUsed($pilot_id)) {
|
||||||
|
Log::info('User with pilot id '.$pilot_id.' exists, reassigning');
|
||||||
|
$pilot_id = $this->userSvc->getNextAvailablePilotId();
|
||||||
|
}
|
||||||
|
|
||||||
|
$attrs = [
|
||||||
|
'pilot_id' => $pilot_id,
|
||||||
|
'name' => $name,
|
||||||
|
'password' => Hash::make($new_password),
|
||||||
|
'api_key' => Utils::generateApiKey(),
|
||||||
|
'airline_id' => $airline_id,
|
||||||
|
'rank_id' => $rank_id,
|
||||||
|
'home_airport_id' => $row->hub,
|
||||||
|
'curr_airport_id' => $row->hub,
|
||||||
|
'flights' => (int) $row->totalflights,
|
||||||
|
'flight_time' => Utils::hoursToMinutes($row->totalhours),
|
||||||
|
'state' => $state,
|
||||||
|
'created_at' => $this->parseDate($row->joindate),
|
||||||
|
];
|
||||||
|
|
||||||
|
$user = User::updateOrCreate(['email' => $row->email], $attrs);
|
||||||
|
$this->idMapper->addMapping('users', $row->pilotid, $user->id);
|
||||||
|
|
||||||
|
$this->updateUserRoles($user, $row->pilotid);
|
||||||
|
|
||||||
|
if ($user->wasRecentlyCreated) {
|
||||||
|
$count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->info('Imported '.$count.' users');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update a user's roles and add them to the proper ones
|
||||||
|
*
|
||||||
|
* @param User $user
|
||||||
|
* @param string $old_pilot_id
|
||||||
|
*/
|
||||||
|
protected function updateUserRoles(User $user, $old_pilot_id)
|
||||||
|
{
|
||||||
|
// Be default add them to the user role, and then determine if they
|
||||||
|
// belong to any other groups, and add them to that
|
||||||
|
$this->userSvc->addUserToRole($user, 'user');
|
||||||
|
|
||||||
|
// Figure out what other groups they belong to
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the user's new state from their original state
|
||||||
|
*
|
||||||
|
* @param $state
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
protected function getUserState($state)
|
||||||
|
{
|
||||||
|
// Return active for now, let the stats/cron determine the status later
|
||||||
|
return UserState::ACTIVE;
|
||||||
|
/*$state = (int) $state;
|
||||||
|
|
||||||
|
// Declare array of classic states
|
||||||
|
$phpvms_classic_states = [
|
||||||
|
'ACTIVE' => 0,
|
||||||
|
'INACTIVE' => 1,
|
||||||
|
'BANNED' => 2,
|
||||||
|
'ON_LEAVE' => 3,
|
||||||
|
];
|
||||||
|
|
||||||
|
// Decide which state they will be in accordance with v7
|
||||||
|
if ($state === $phpvms_classic_states['ACTIVE']) {
|
||||||
|
return UserState::ACTIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($state === $phpvms_classic_states['INACTIVE']) {
|
||||||
|
// TODO: Make an inactive state?
|
||||||
|
return UserState::REJECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($state === $phpvms_classic_states['BANNED']) {
|
||||||
|
return UserState::SUSPENDED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($state === $phpvms_classic_states['ON_LEAVE']) {
|
||||||
|
return UserState::ON_LEAVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->error('Unknown status: '.$state);
|
||||||
|
|
||||||
|
return UserState::ACTIVE;*/
|
||||||
|
}
|
||||||
|
}
|
||||||
97
modules/Installer/Services/Importer/Stages/Stage1.php
Normal file
97
modules/Installer/Services/Importer/Stages/Stage1.php
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Installer\Services\Importer\Stages;
|
||||||
|
|
||||||
|
use App\Models\Acars;
|
||||||
|
use App\Models\Airline;
|
||||||
|
use App\Models\Airport;
|
||||||
|
use App\Models\Bid;
|
||||||
|
use App\Models\Expense;
|
||||||
|
use App\Models\File;
|
||||||
|
use App\Models\Flight;
|
||||||
|
use App\Models\FlightField;
|
||||||
|
use App\Models\FlightFieldValue;
|
||||||
|
use App\Models\Journal;
|
||||||
|
use App\Models\JournalTransaction;
|
||||||
|
use App\Models\News;
|
||||||
|
use App\Models\Pirep;
|
||||||
|
use App\Models\Subfleet;
|
||||||
|
use App\Models\User;
|
||||||
|
use App\Models\UserAward;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Modules\Installer\Exceptions\ImporterNextRecordSet;
|
||||||
|
use Modules\Installer\Exceptions\StageCompleted;
|
||||||
|
use Modules\Installer\Services\Importer\BaseStage;
|
||||||
|
use Modules\Installer\Services\Importer\Importers\AircraftImporter;
|
||||||
|
use Modules\Installer\Services\Importer\Importers\AirlineImporter;
|
||||||
|
use Modules\Installer\Services\Importer\Importers\GroupImporter;
|
||||||
|
use Modules\Installer\Services\Importer\Importers\RankImport;
|
||||||
|
|
||||||
|
class Stage1 extends BaseStage
|
||||||
|
{
|
||||||
|
public $importers = [
|
||||||
|
RankImport::class,
|
||||||
|
AirlineImporter::class,
|
||||||
|
AircraftImporter::class,
|
||||||
|
GroupImporter::class,
|
||||||
|
];
|
||||||
|
|
||||||
|
public $nextStage = 'stage2';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $start Record number to start from
|
||||||
|
*
|
||||||
|
* @throws ImporterNextRecordSet
|
||||||
|
* @throws StageCompleted
|
||||||
|
*/
|
||||||
|
public function run($start = 0)
|
||||||
|
{
|
||||||
|
$this->cleanupDb();
|
||||||
|
|
||||||
|
// Run the first set of importers
|
||||||
|
parent::run($start);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cleanup the local database of any users and other data that might conflict
|
||||||
|
* before running the importer
|
||||||
|
*/
|
||||||
|
protected function cleanupDb()
|
||||||
|
{
|
||||||
|
$this->info('Running database cleanup/empty before starting');
|
||||||
|
|
||||||
|
Bid::truncate();
|
||||||
|
File::truncate();
|
||||||
|
News::truncate();
|
||||||
|
|
||||||
|
Expense::truncate();
|
||||||
|
JournalTransaction::truncate();
|
||||||
|
Journal::truncate();
|
||||||
|
|
||||||
|
// Clear flights
|
||||||
|
DB::table('flight_fare')->truncate();
|
||||||
|
DB::table('flight_subfleet')->truncate();
|
||||||
|
FlightField::truncate();
|
||||||
|
FlightFieldValue::truncate();
|
||||||
|
Flight::truncate();
|
||||||
|
Subfleet::truncate();
|
||||||
|
|
||||||
|
// Clear permissions
|
||||||
|
// DB::table('permission_role')->truncate();
|
||||||
|
// DB::table('permission_user')->truncate();
|
||||||
|
// DB::table('role_user')->truncate();
|
||||||
|
// Role::truncate();
|
||||||
|
|
||||||
|
Airline::truncate();
|
||||||
|
Airport::truncate();
|
||||||
|
Acars::truncate();
|
||||||
|
Pirep::truncate();
|
||||||
|
|
||||||
|
UserAward::truncate();
|
||||||
|
User::truncate();
|
||||||
|
|
||||||
|
// Re-run the base seeds
|
||||||
|
//$seederSvc = app(SeederService::class);
|
||||||
|
//$seederSvc->syncAllSeeds();
|
||||||
|
}
|
||||||
|
}
|
||||||
15
modules/Installer/Services/Importer/Stages/Stage2.php
Normal file
15
modules/Installer/Services/Importer/Stages/Stage2.php
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Installer\Services\Importer\Stages;
|
||||||
|
|
||||||
|
use Modules\Installer\Services\Importer\BaseStage;
|
||||||
|
use Modules\Installer\Services\Importer\Importers\AirportImporter;
|
||||||
|
|
||||||
|
class Stage2 extends BaseStage
|
||||||
|
{
|
||||||
|
public $importers = [
|
||||||
|
AirportImporter::class,
|
||||||
|
];
|
||||||
|
|
||||||
|
public $nextStage = 'stage3';
|
||||||
|
}
|
||||||
15
modules/Installer/Services/Importer/Stages/Stage3.php
Normal file
15
modules/Installer/Services/Importer/Stages/Stage3.php
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Installer\Services\Importer\Stages;
|
||||||
|
|
||||||
|
use Modules\Installer\Services\Importer\BaseStage;
|
||||||
|
use Modules\Installer\Services\Importer\Importers\UserImport;
|
||||||
|
|
||||||
|
class Stage3 extends BaseStage
|
||||||
|
{
|
||||||
|
public $importers = [
|
||||||
|
UserImport::class,
|
||||||
|
];
|
||||||
|
|
||||||
|
public $nextStage = 'stage4';
|
||||||
|
}
|
||||||
15
modules/Installer/Services/Importer/Stages/Stage4.php
Normal file
15
modules/Installer/Services/Importer/Stages/Stage4.php
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Installer\Services\Importer\Stages;
|
||||||
|
|
||||||
|
use Modules\Installer\Services\Importer\BaseStage;
|
||||||
|
use Modules\Installer\Services\Importer\Importers\FlightImporter;
|
||||||
|
|
||||||
|
class Stage4 extends BaseStage
|
||||||
|
{
|
||||||
|
public $importers = [
|
||||||
|
FlightImporter::class,
|
||||||
|
];
|
||||||
|
|
||||||
|
public $nextStage = 'stage5';
|
||||||
|
}
|
||||||
15
modules/Installer/Services/Importer/Stages/Stage5.php
Normal file
15
modules/Installer/Services/Importer/Stages/Stage5.php
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Installer\Services\Importer\Stages;
|
||||||
|
|
||||||
|
use Modules\Installer\Services\Importer\BaseStage;
|
||||||
|
use Modules\Installer\Services\Importer\Importers\PirepImporter;
|
||||||
|
|
||||||
|
class Stage5 extends BaseStage
|
||||||
|
{
|
||||||
|
public $importers = [
|
||||||
|
PirepImporter::class,
|
||||||
|
];
|
||||||
|
|
||||||
|
public $nextStage = 'stage6';
|
||||||
|
}
|
||||||
41
modules/Installer/Services/Importer/Stages/Stage6.php
Normal file
41
modules/Installer/Services/Importer/Stages/Stage6.php
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Installer\Services\Importer\Stages;
|
||||||
|
|
||||||
|
use App\Models\User;
|
||||||
|
use App\Services\UserService;
|
||||||
|
use Modules\Installer\Exceptions\StageCompleted;
|
||||||
|
use Modules\Installer\Services\Importer\BaseStage;
|
||||||
|
|
||||||
|
class Stage6 extends BaseStage
|
||||||
|
{
|
||||||
|
public $nextStage = 'complete';
|
||||||
|
|
||||||
|
public function run($start = 0)
|
||||||
|
{
|
||||||
|
$this->findLastPireps();
|
||||||
|
$this->recalculateUserStats();
|
||||||
|
|
||||||
|
throw new StageCompleted($this->nextStage);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Go through and set the last PIREP ID for the users
|
||||||
|
*/
|
||||||
|
protected function findLastPireps()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recalculate all of the user stats
|
||||||
|
*/
|
||||||
|
protected function recalculateUserStats()
|
||||||
|
{
|
||||||
|
$this->comment('--- RECALCULATING USER STATS ---');
|
||||||
|
$userSvc = app(UserService::class);
|
||||||
|
|
||||||
|
User::all()->each(function ($user) use ($userSvc) {
|
||||||
|
$userSvc->recalculateStats($user);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
49
modules/Installer/Utils/IdMapper.php
Normal file
49
modules/Installer/Utils/IdMapper.php
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Installer\Utils;
|
||||||
|
|
||||||
|
use App\Contracts\Service;
|
||||||
|
use Spatie\Valuestore\Valuestore;
|
||||||
|
|
||||||
|
class IdMapper extends Service
|
||||||
|
{
|
||||||
|
private $valueStore;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->valueStore = Valuestore::make(storage_path('app/legacy_migration.json'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new mapping between an old ID and the new one
|
||||||
|
*
|
||||||
|
* @param string $entity Name of the entity (e,g table)
|
||||||
|
* @param string $old_id
|
||||||
|
* @param string $new_id
|
||||||
|
*/
|
||||||
|
public function addMapping($entity, $old_id, $new_id)
|
||||||
|
{
|
||||||
|
$key_name = $entity.'_'.$old_id;
|
||||||
|
if (!$this->valueStore->has($key_name)) {
|
||||||
|
$this->valueStore->put($key_name, $new_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the ID for a mapping
|
||||||
|
*
|
||||||
|
* @param $entity
|
||||||
|
* @param $old_id
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function getMapping($entity, $old_id)
|
||||||
|
{
|
||||||
|
$key_name = $entity.'_'.$old_id;
|
||||||
|
if (!$this->valueStore->has($key_name)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->valueStore->get($key_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
159
modules/Installer/Utils/ImporterDB.php
Normal file
159
modules/Installer/Utils/ImporterDB.php
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Installer\Utils;
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Modules\Installer\Exceptions\ImporterNextRecordSet;
|
||||||
|
use Modules\Installer\Exceptions\ImporterNoMoreRecords;
|
||||||
|
use PDO;
|
||||||
|
use PDOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Real basic to interface with an importer
|
||||||
|
*/
|
||||||
|
class ImporterDB
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var PDO
|
||||||
|
*/
|
||||||
|
private $conn;
|
||||||
|
|
||||||
|
private $dsn;
|
||||||
|
private $creds;
|
||||||
|
private $batchSize;
|
||||||
|
|
||||||
|
public function __construct($creds)
|
||||||
|
{
|
||||||
|
$this->creds = $creds;
|
||||||
|
$this->dsn = 'mysql:'.implode(';', [
|
||||||
|
'host='.$this->creds['host'],
|
||||||
|
'port='.$this->creds['port'],
|
||||||
|
'dbname='.$this->creds['name'],
|
||||||
|
]);
|
||||||
|
|
||||||
|
Log::info('Using DSN: '.$this->dsn);
|
||||||
|
|
||||||
|
$this->batchSize = config('installer.importer.batch_size');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function connect()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$this->conn = new PDO($this->dsn, $this->creds['user'], $this->creds['pass']);
|
||||||
|
$this->conn->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
Log::error($e);
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the table name with the prefix
|
||||||
|
*
|
||||||
|
* @param $table
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function tableName($table)
|
||||||
|
{
|
||||||
|
if ($this->creds['table_prefix'] !== false) {
|
||||||
|
return $this->creds['table_prefix'].$table;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $table;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $table
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function getTotalRows($table)
|
||||||
|
{
|
||||||
|
$this->connect();
|
||||||
|
|
||||||
|
$sql = 'SELECT COUNT(*) FROM '.$this->tableName($table);
|
||||||
|
$rows = $this->conn->query($sql)->fetchColumn();
|
||||||
|
|
||||||
|
Log::info('Found '.$rows.' rows in '.$table);
|
||||||
|
|
||||||
|
return (int) $rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read all the rows in a table, but read them in a batched manner
|
||||||
|
*
|
||||||
|
* @param string $table The name of the table
|
||||||
|
* @param int [$start_offset]
|
||||||
|
*
|
||||||
|
* @throws \Modules\Installer\Exceptions\ImporterNextRecordSet
|
||||||
|
* @throws \Modules\Installer\Exceptions\ImporterNoMoreRecords
|
||||||
|
*
|
||||||
|
* @return \Generator
|
||||||
|
*/
|
||||||
|
public function readRows($table, $start_offset = 0)
|
||||||
|
{
|
||||||
|
$this->connect();
|
||||||
|
|
||||||
|
$offset = $start_offset;
|
||||||
|
$total_rows = $this->getTotalRows($table);
|
||||||
|
|
||||||
|
while ($offset < $total_rows) {
|
||||||
|
$rows_to_read = $offset + $this->batchSize;
|
||||||
|
if ($rows_to_read > $total_rows) {
|
||||||
|
$rows_to_read = $total_rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
Log::info('Reading '.$offset.' to '.$rows_to_read.' of '.$total_rows);
|
||||||
|
yield from $this->readRowsOffset($table, $this->batchSize, $offset);
|
||||||
|
|
||||||
|
$offset += $this->batchSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $table
|
||||||
|
* @param int $limit Number of rows to read
|
||||||
|
* @param int $offset Where to start from
|
||||||
|
*
|
||||||
|
* @throws ImporterNextRecordSet
|
||||||
|
* @throws ImporterNoMoreRecords
|
||||||
|
*
|
||||||
|
* @return \Generator
|
||||||
|
*/
|
||||||
|
public function readRowsOffset($table, $limit, $offset)
|
||||||
|
{
|
||||||
|
$sql = 'SELECT * FROM '.$this->tableName($table).' LIMIT '.$limit.' OFFSET '.$offset;
|
||||||
|
|
||||||
|
try {
|
||||||
|
$result = $this->conn->query($sql);
|
||||||
|
if (!$result) {
|
||||||
|
throw new ImporterNoMoreRecords();
|
||||||
|
}
|
||||||
|
|
||||||
|
$rowCount = $result->rowCount();
|
||||||
|
|
||||||
|
if (!$rowCount === 0) {
|
||||||
|
throw new ImporterNoMoreRecords();
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($result as $row) {
|
||||||
|
yield $row;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No more records left since we got the number below the limit
|
||||||
|
if ($rowCount < $limit) {
|
||||||
|
throw new ImporterNoMoreRecords();
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new ImporterNextRecordSet($offset + $limit);
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
// Without incrementing the offset, it should re-run the same query
|
||||||
|
Log::error('Error readRowsOffset: '.$e->getMessage());
|
||||||
|
|
||||||
|
if (strpos($e->getMessage(), 'server has gone away') !== false) {
|
||||||
|
$this->connect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
23
modules/Installer/Utils/LoggerTrait.php
Normal file
23
modules/Installer/Utils/LoggerTrait.php
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Modules\Installer\Utils;
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
|
trait LoggerTrait
|
||||||
|
{
|
||||||
|
protected function comment($text)
|
||||||
|
{
|
||||||
|
Log::info($text);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function info($text)
|
||||||
|
{
|
||||||
|
Log::info($text);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function error($text)
|
||||||
|
{
|
||||||
|
Log::error($text);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,92 +1,98 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<title>@yield('title') - {{ config('app.name') }} admin</title>
|
<title>@yield('title') - {{ config('app.name') }} admin</title>
|
||||||
|
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8"/>
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
|
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
|
||||||
<meta content='width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0' name='viewport' />
|
<meta content='width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0' name='viewport'/>
|
||||||
<meta name="viewport" content="width=device-width" />
|
<meta name="viewport" content="width=device-width"/>
|
||||||
|
|
||||||
{{-- Start of required lines block. DON'T REMOVE THESE LINES! They're required or might break things --}}
|
{{-- Start of required lines block. DON'T REMOVE THESE LINES! They're required or might break things --}}
|
||||||
<meta name="base-url" content="{{ url('') }}">
|
<meta name="base-url" content="{{ url('') }}">
|
||||||
<meta name="csrf-token" content="{{ csrf_token() }}">
|
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||||||
<meta name="api-key" content="{{ Auth::check() ? Auth::user()->api_key: '' }}">
|
<meta name="api-key" content="{{ Auth::check() ? Auth::user()->api_key: '' }}">
|
||||||
{{-- End the required lines block --}}
|
{{-- End the required lines block --}}
|
||||||
|
|
||||||
<script src="{{ public_asset('/assets/global/js/jquery.js') }}"></script>
|
<script src="{{ public_asset('/assets/global/js/jquery.js') }}"></script>
|
||||||
|
|
||||||
<link rel="shortcut icon" type="image/png" href="{{ public_asset('/assets/img/favicon.png') }}"/>
|
<link rel="shortcut icon" type="image/png" href="{{ public_asset('/assets/img/favicon.png') }}"/>
|
||||||
|
|
||||||
<link href='https://fonts.googleapis.com/css?family=Muli:400,300' rel='stylesheet' type='text/css'/>
|
<link href='https://fonts.googleapis.com/css?family=Muli:400,300' rel='stylesheet' type='text/css'/>
|
||||||
<link href="https://fonts.googleapis.com/css?family=Roboto:400,700,300" rel="stylesheet" type="text/css"/>
|
<link href="https://fonts.googleapis.com/css?family=Roboto:400,700,300" rel="stylesheet" type="text/css"/>
|
||||||
|
|
||||||
<link rel="stylesheet" href="{{ public_mix('/assets/global/css/vendor.css') }}"/>
|
<link rel="stylesheet" href="{{ public_mix('/assets/global/css/vendor.css') }}"/>
|
||||||
<link rel="stylesheet" href="{{ public_mix('/assets/admin/css/vendor.css') }}"/>
|
<link rel="stylesheet" href="{{ public_mix('/assets/admin/css/vendor.css') }}"/>
|
||||||
<link rel="stylesheet" href="{{ public_asset('/assets/admin/css/admin.css') }}"/>
|
<link rel="stylesheet" href="{{ public_asset('/assets/admin/css/admin.css') }}"/>
|
||||||
|
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
@yield('css')
|
@yield('css')
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
const BASE_URL ='{{ url('/') }}';
|
const BASE_URL = '{{ url('/') }}';
|
||||||
@if (Auth::user())
|
@if (Auth::user())
|
||||||
const PHPVMS_USER_API_KEY = "{{ Auth::user()->api_key }}";
|
const PHPVMS_USER_API_KEY = "{{ Auth::user()->api_key }}";
|
||||||
@else
|
@else
|
||||||
const PHPVMS_USER_API_KEY = false;
|
const PHPVMS_USER_API_KEY = false;
|
||||||
@endif
|
@endif
|
||||||
@yield('scripts_head')
|
@yield('scripts_head')
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<div class="wrapper">
|
<div class="wrapper">
|
||||||
@include('admin.sidebar')
|
@include('admin.sidebar')
|
||||||
|
|
||||||
<div class="main-panel">
|
<div class="main-panel">
|
||||||
<nav class="navbar navbar-default">
|
<nav class="navbar navbar-default">
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<div class="navbar-header">
|
<div class="navbar-header">
|
||||||
<button type="button" class="navbar-toggle">
|
<button type="button" class="navbar-toggle">
|
||||||
<span class="sr-only">Toggle navigation</span>
|
<span class="sr-only">Toggle navigation</span>
|
||||||
<span class="icon-bar bar1"></span>
|
<span class="icon-bar bar1"></span>
|
||||||
<span class="icon-bar bar2"></span>
|
<span class="icon-bar bar2"></span>
|
||||||
<span class="icon-bar bar3"></span>
|
<span class="icon-bar bar3"></span>
|
||||||
</button>
|
</button>
|
||||||
<a class="navbar-brand" href="#">@yield('title')</a>
|
<a class="navbar-brand" href="#">@yield('title')</a>
|
||||||
</div>
|
|
||||||
<div class="collapse navbar-collapse">
|
|
||||||
<ul class="nav navbar-nav navbar-right">
|
|
||||||
@yield('actions')
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="content">
|
|
||||||
<div class="container-fluid">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-12">
|
|
||||||
@include('admin.flash.message')
|
|
||||||
@yield('content')
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="collapse navbar-collapse">
|
||||||
|
<ul class="nav navbar-nav navbar-right">
|
||||||
|
@yield('actions')
|
||||||
|
</ul>
|
||||||
|
|
||||||
<footer class="footer">
|
</div>
|
||||||
<div class="container-fluid">
|
</div>
|
||||||
<nav class="pull-left">
|
</nav>
|
||||||
<ul>
|
|
||||||
</ul>
|
|
||||||
</nav>
|
<div class="content">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row">
|
||||||
|
@if(\App\Support\Utils::installerEnabled())
|
||||||
|
<div class="col-lg-12 alert alert-danger alert-important">
|
||||||
|
<p>Remove the modules/Installer folder or set the module to disabled! It's a security risk</p>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
@endif
|
||||||
|
|
||||||
|
<div class="col-12">
|
||||||
|
@include('admin.flash.message')
|
||||||
|
@yield('content')
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<footer class="footer">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<nav class="pull-left">
|
||||||
|
<ul>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
@@ -95,59 +101,59 @@
|
|||||||
<script defer src="{{ public_mix('/assets/admin/js/app.js') }}"></script>
|
<script defer src="{{ public_mix('/assets/admin/js/app.js') }}"></script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
/**
|
/**
|
||||||
* Initialize any plugins on the page
|
* Initialize any plugins on the page
|
||||||
*/
|
*/
|
||||||
const initPlugins = () => {
|
const initPlugins = () => {
|
||||||
$('.select2').select2({width: 'resolve'});
|
$('.select2').select2({width: 'resolve'});
|
||||||
$('input').iCheck({
|
$('input').iCheck({
|
||||||
checkboxClass: 'icheckbox_square-blue',
|
checkboxClass: 'icheckbox_square-blue',
|
||||||
radioClass: 'icheckbox_square-blue'
|
radioClass: 'icheckbox_square-blue'
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
initPlugins();
|
initPlugins();
|
||||||
|
|
||||||
//let storage = getStorage('phpvms.admin');
|
//let storage = getStorage('phpvms.admin');
|
||||||
const storage = new phpvms.Storage('phpvms.admin', {
|
const storage = new phpvms.Storage('phpvms.admin', {
|
||||||
"menu": [],
|
"menu": [],
|
||||||
});
|
});
|
||||||
|
|
||||||
// see what menu items should be open
|
// see what menu items should be open
|
||||||
const menu = storage.getList('menu');
|
const menu = storage.getList('menu');
|
||||||
for (const id of menu) {
|
for (const id of menu) {
|
||||||
console.log('found '+id);
|
console.log('found ' + id);
|
||||||
const elem = $(".collapse#" + id);
|
const elem = $(".collapse#" + id);
|
||||||
elem.addClass("in").trigger("show.bs.collapse");
|
elem.addClass("in").trigger("show.bs.collapse");
|
||||||
|
|
||||||
const caret = $("a." + id + " b");
|
const caret = $("a." + id + " b");
|
||||||
caret.addClass("pe-7s-angle-down");
|
caret.addClass("pe-7s-angle-down");
|
||||||
caret.removeClass("pe-7s-angle-right");
|
caret.removeClass("pe-7s-angle-right");
|
||||||
}
|
}
|
||||||
|
|
||||||
$(".collapse").on("hide.bs.collapse", function() {
|
$(".collapse").on("hide.bs.collapse", function () {
|
||||||
const id = $(this).attr('id');
|
const id = $(this).attr('id');
|
||||||
const elem = $("a." + id + " b");
|
const elem = $("a." + id + " b");
|
||||||
elem.removeClass("pe-7s-angle-down");
|
elem.removeClass("pe-7s-angle-down");
|
||||||
elem.addClass("pe-7s-angle-right");
|
elem.addClass("pe-7s-angle-right");
|
||||||
|
|
||||||
// console.log('hiding ' + id);
|
// console.log('hiding ' + id);
|
||||||
storage.removeFromList('menu', id);
|
storage.removeFromList('menu', id);
|
||||||
storage.save();
|
storage.save();
|
||||||
});
|
});
|
||||||
|
|
||||||
$(".collapse").on("show.bs.collapse", function() {
|
$(".collapse").on("show.bs.collapse", function () {
|
||||||
const id = $(this).attr('id');
|
const id = $(this).attr('id');
|
||||||
const caret = $("a." + id + " b");
|
const caret = $("a." + id + " b");
|
||||||
caret.addClass("pe-7s-angle-down");
|
caret.addClass("pe-7s-angle-down");
|
||||||
caret.removeClass("pe-7s-angle-right");
|
caret.removeClass("pe-7s-angle-right");
|
||||||
|
|
||||||
// console.log('showing ' + id);
|
// console.log('showing ' + id);
|
||||||
storage.addToList('menu', id);
|
storage.addToList('menu', id);
|
||||||
storage.save();
|
storage.save();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@yield('scripts')
|
@yield('scripts')
|
||||||
|
|||||||
@@ -1,59 +1,59 @@
|
|||||||
@extends('admin.app')
|
@extends('admin.app')
|
||||||
@section('title', 'Dashboard')
|
@section('title', 'Dashboard')
|
||||||
@section('content')
|
@section('content')
|
||||||
<div class="content">
|
<div class="content">
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-7">
|
<div class="col-md-7">
|
||||||
@include('admin.dashboard.news')
|
@include('admin.dashboard.news')
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-5">
|
<div class="col-md-5">
|
||||||
@component('admin.components.infobox')
|
@component('admin.components.infobox')
|
||||||
@slot('icon', 'pe-7s-users')
|
@slot('icon', 'pe-7s-users')
|
||||||
@slot('type', 'Pilots')
|
@slot('type', 'Pilots')
|
||||||
@slot('pending', $pending_users)
|
@slot('pending', $pending_users)
|
||||||
@slot('link', route('admin.users.index').'?state='.UserState::PENDING)
|
@slot('link', route('admin.users.index').'?state='.UserState::PENDING)
|
||||||
@endcomponent
|
@endcomponent
|
||||||
|
|
||||||
@component('admin.components.infobox')
|
@component('admin.components.infobox')
|
||||||
@slot('icon', 'pe-7s-cloud-upload')
|
@slot('icon', 'pe-7s-cloud-upload')
|
||||||
@slot('type', 'PIREPs')
|
@slot('type', 'PIREPs')
|
||||||
@slot('pending', $pending_pireps)
|
@slot('pending', $pending_pireps)
|
||||||
@slot('link', route('admin.pireps.index').'?search=state:'.PirepState::PENDING)
|
@slot('link', route('admin.pireps.index').'?search=state:'.PirepState::PENDING)
|
||||||
@endcomponent
|
@endcomponent
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-6">
|
|
||||||
{{--@include('admin.dashboard.pirep_chart')--}}
|
|
||||||
</div>
|
|
||||||
<div class="col-md-6">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-6">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div class="col-md-6">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6">
|
||||||
|
{{--@include('admin.dashboard.pirep_chart')--}}
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@endsection
|
@endsection
|
||||||
@section('scripts')
|
@section('scripts')
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(function() {
|
$(document).ready(function () {
|
||||||
$(document).on('submit', 'form.pjax_news_form', function (event) {
|
$(document).on('submit', 'form.pjax_news_form', function (event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
$.pjax.submit(event, '#pjax_news_wrapper', {push: false});
|
$.pjax.submit(event, '#pjax_news_wrapper', {push: false});
|
||||||
});
|
});
|
||||||
|
|
||||||
/*$(document).on('pjax:complete', function () {
|
/*$(document).on('pjax:complete', function () {
|
||||||
$(".select2").select2();
|
$(".select2").select2();
|
||||||
});*/
|
});*/
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
@endsection
|
@endsection
|
||||||
|
|||||||
Reference in New Issue
Block a user