diff --git a/app/Console/Services/Importer.php b/app/Console/Services/Importer.php deleted file mode 100644 index 1d727bc24..000000000 --- a/app/Console/Services/Importer.php +++ /dev/null @@ -1,704 +0,0 @@ -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(''.$message.''); - } - - /** - * @param $message - */ - protected function error($message) - { - $this->log->writeln(''.$message.''); - } - - /** - * @param string|array $message - */ - protected function info($message) - { - if (\is_array($message)) { - /* @noinspection ForgottenDebugOutputInspection */ - print_r($message); - } else { - $this->log->writeln(''.$message.''); - } - } - - /** - * 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; - } -} diff --git a/app/Contracts/Model.php b/app/Contracts/Model.php index e186e9363..e4111609f 100644 --- a/app/Contracts/Model.php +++ b/app/Contracts/Model.php @@ -9,6 +9,8 @@ * @property bool $skip_mutator * * @method static where(array $array) + * @method static updateOrCreate(array $array, array $attrs) + * @method static truncate() */ abstract class Model extends \Illuminate\Database\Eloquent\Model { diff --git a/app/Database/migrations/2019_07_16_141152_users_add_pilot_id.php b/app/Database/migrations/2019_07_16_141152_users_add_pilot_id.php index 29ad73a47..caad035cf 100644 --- a/app/Database/migrations/2019_07_16_141152_users_add_pilot_id.php +++ b/app/Database/migrations/2019_07_16_141152_users_add_pilot_id.php @@ -28,28 +28,6 @@ public function up() // Migrate the current pilot IDs 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 } /** diff --git a/app/Database/seeds/permissions.yml b/app/Database/seeds/permissions.yml index a1fd89f6e..222cc5189 100644 --- a/app/Database/seeds/permissions.yml +++ b/app/Database/seeds/permissions.yml @@ -1,7 +1,7 @@ # All of the different permissions that can be assigned to roles --- - name: admin-access - display_name: Admin Access + display_name: Administrator description: Access the admin panel - name: airlines display_name: Airlines diff --git a/app/Http/Controllers/Admin/RolesController.php b/app/Http/Controllers/Admin/RolesController.php index 00362ba09..daca92458 100644 --- a/app/Http/Controllers/Admin/RolesController.php +++ b/app/Http/Controllers/Admin/RolesController.php @@ -7,29 +7,33 @@ use App\Http\Requests\UpdateRoleRequest; use App\Repositories\PermissionsRepository; use App\Repositories\RoleRepository; -use Flash; +use App\Services\RoleService; use Illuminate\Http\Request; +use Illuminate\Http\Response; +use Laracasts\Flash\Flash; use Prettus\Repository\Criteria\RequestCriteria; -use Response; -/** - * Class AirlinesController - */ class RolesController extends Controller { private $permsRepo; private $rolesRepo; + private $roleSvc; /** * AirlinesController constructor. * * @param PermissionsRepository $permsRepo * @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->rolesRepo = $rolesRepo; + $this->roleSvc = $roleSvc; } /** @@ -145,14 +149,8 @@ public function update($id, UpdateRoleRequest $request) return redirect(route('admin.roles.index')); } - $this->rolesRepo->update($request->all(), $id); - - // Update the permissions, filter out null/invalid values - $perms = collect($request->permissions)->filter(static function ($v, $k) { - return $v; - }); - - $role->permissions()->sync($perms); + $this->roleSvc->updateRole($role, $request->all()); + $this->roleSvc->setPermissionsForRole($role, $request->permissions); Flash::success('Roles updated successfully.'); return redirect(route('admin.roles.index')); diff --git a/app/Models/Permission.php b/app/Models/Permission.php index beaa2e89c..94a893e96 100644 --- a/app/Models/Permission.php +++ b/app/Models/Permission.php @@ -4,6 +4,9 @@ use Laratrust\Models\LaratrustPermission; +/** + * @method static firstOrCreate(array $array, array $array1) + */ class Permission extends LaratrustPermission { } diff --git a/app/Models/Role.php b/app/Models/Role.php index 176165d73..6ddf1cf08 100644 --- a/app/Models/Role.php +++ b/app/Models/Role.php @@ -6,6 +6,7 @@ /** * @method static where(string $string, $group) + * @method static firstOrCreate(array $array, array $array1) */ class Role extends LaratrustRole { diff --git a/app/Models/User.php b/app/Models/User.php index 69a1f67df..eae1e6b60 100755 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -34,6 +34,10 @@ * @property int state * @property bool opt_in * @property string last_pirep_id + * + * @method static updateOrCreate(array $array, array $attrs) + * @method static where() + * @method static truncate() * @mixin \Illuminate\Notifications\Notifiable * @mixin \Laratrust\Traits\LaratrustUserTrait */ diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 08de6322b..9b3acf514 100755 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -26,8 +26,8 @@ use App\Repositories\SettingRepository; use App\Services\ModuleService; use Illuminate\Support\Facades\Schema; +use Illuminate\Support\Facades\View; use Illuminate\Support\ServiceProvider; -use View; class AppServiceProvider extends ServiceProvider { diff --git a/app/Services/Installer/SeederService.php b/app/Services/Installer/SeederService.php index 2ae2fed94..c0303cd8b 100644 --- a/app/Services/Installer/SeederService.php +++ b/app/Services/Installer/SeederService.php @@ -236,6 +236,13 @@ private function settingsSeedsPending(): bool return true; } + // See if any of these column values have changed + foreach (['name', 'description'] as $column) { + if ($row[$column] !== $setting[$column]) { + return true; + } + } + // See if any of the options have changed if ($row->type === 'select') { if ($row->options !== $setting['options']) { @@ -259,10 +266,20 @@ private function permissionsSeedsPending(): bool $yml = Yaml::parse($data); foreach ($yml as $perm) { - $count = DB::table('permissions')->where('name', $perm['name'])->count('name'); - if ($count === 0) { + $row = DB::table('permissions') + ->where('name', $perm['name']) + ->first(); + + if (!$row) { 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; diff --git a/app/Services/RoleService.php b/app/Services/RoleService.php new file mode 100644 index 000000000..1b6c00588 --- /dev/null +++ b/app/Services/RoleService.php @@ -0,0 +1,47 @@ +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); + } +} diff --git a/app/Services/UserService.php b/app/Services/UserService.php index bc233a7ab..bc62636bb 100644 --- a/app/Services/UserService.php +++ b/app/Services/UserService.php @@ -48,14 +48,14 @@ public function __construct( * Register a pilot. Also attaches the initial roles * required, and then triggers the UserRegistered event * - * @param User $user User model - * @param array $groups Additional groups to assign + * @param User $user User model + * @param array $roles List of "display_name" of groups to assign * * @throws \Exception * * @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 if (setting('pilots.auto_accept') === true) { @@ -66,15 +66,10 @@ public function createUser(User $user, array $groups = null) $user->save(); - // Attach the user roles - // $role = Role::where('name', 'user')->first(); - // $user->attachRole($role); - // Attach any additional roles - if (!empty($groups) && is_array($groups)) { - foreach ($groups as $group) { - $role = Role::where('name', $group)->first(); - $user->attachRole($role); + if (!empty($roles) && is_array($roles)) { + foreach ($roles as $role) { + $this->addUserToRole($user, $role); } } @@ -87,6 +82,32 @@ public function createUser(User $user, array $groups = null) 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 * Called from UserObserver right now after a record is created @@ -101,8 +122,7 @@ public function findAndSetPilotId(User $user): User return $user; } - $max = (int) User::max('pilot_id'); - $user->pilot_id = $max + 1; + $user->pilot_id = $this->getNextAvailablePilotId(); $user->save(); Log::info('Set pilot ID for user '.$user->id.' to '.$user->pilot_id); diff --git a/intellij_style.xml b/intellij_style.xml index 903cf02a8..9c0b52567 100644 --- a/intellij_style.xml +++ b/intellij_style.xml @@ -1,16 +1,15 @@ - - + + + + +