Compare commits

..

5 Commits

Author SHA1 Message Date
nabeelio
db34d0e3e7 Add test for METAR string 2021-03-15 09:14:39 -04:00
Nabeel S
fffbab7201 Merge branch 'dev' into patch-2 2021-03-15 08:30:29 -04:00
B.Fatih KOZ
76a2a16fa6 Merge branch 'dev' into patch-2 2021-03-14 03:54:53 +03:00
B.Fatih KOZ
cfbd1c901a Merge branch 'dev' into patch-2 2021-03-10 04:53:25 +03:00
B.Fatih KOZ
617813bdbf Fix Metar Decoding / Wind check for Wind Chill
PR aims to fix the bug #1071 by checking both the wind speed and it's value for starting Wind Chill calculation.
2021-03-09 16:06:39 +03:00
378 changed files with 55719 additions and 34402 deletions

View File

@@ -30,7 +30,6 @@ declare -a remove_files=(
intellij_style.xml
config.php
docker-compose.yml
docker-compose.local.yml
Makefile
phpcs.xml
phpunit.xml
@@ -70,25 +69,13 @@ mkdir -p storage/framework/views
cd /tmp
echo "Current directory contents"
ls -al $BASE_DIR
echo "Parent directory contents"
ls -al $BASE_DIR/../
echo "Calling find"
find $BASE_DIR/../ -type d -maxdepth 2
tar -czf $TAR_NAME -C $BASE_DIR --xform 's:^\./::' . [--show-transformed-names|--show-stored-names]
tar -czf $TAR_NAME -C $BASE_DIR .
sha256sum $TAR_NAME >"$TAR_NAME.sha256"
cd $BASE_DIR;
zip -r $ZIP_NAME ./
tar2zip $TAR_NAME
sha256sum $ZIP_NAME >"$ZIP_NAME.sha256"
mv $ZIP_NAME /tmp
mv "$ZIP_NAME.sha256" /tmp
ls -al /tmp
echo "Moving to dist"

View File

@@ -8,7 +8,7 @@ APP_LOCALE="en"
PHPVMS_INSTALLED="true"
APP_LOG="daily"
LOG_LEVEL="debug"
APP_LOG_LEVEL="debug"
APP_LOG_MAX_FILES="3"
DB_CONNECTION="mysql"

View File

@@ -7,7 +7,7 @@ jobs:
strategy:
fail-fast: true
matrix:
php-versions: ['7.3', '7.4', '8.0']
php-versions: ['7.3', '7.4']
name: PHP ${{ matrix.php-versions }}
env:
extensions: intl, pcov, mbstring
@@ -41,6 +41,7 @@ jobs:
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: ${{ runner.os }}-composer-
# Configure PHP
- name: Setup PHP
@@ -116,6 +117,7 @@ jobs:
- name: 'Install Release Dependencies'
run: |
rm -rf vendor
sudo npm i tar-to-zip -g
composer install --no-dev --prefer-dist --no-interaction --verbose
sudo chmod +x ./.github/scripts/*
@@ -178,6 +180,7 @@ jobs:
- name: 'Install Release Dependencies'
run: |
rm -rf vendor
sudo npm i tar-to-zip -g
composer install --no-dev --prefer-dist --no-interaction --verbose
sudo chmod +x ./.github/scripts/*

1
.gitignore vendored
View File

@@ -74,5 +74,4 @@ error_log
.sass-cache
.DS_Store
/config.php
/config.bak.php
/VERSION

View File

@@ -28,8 +28,6 @@ RedirectMatch 403 ^/composer.phar
RedirectMatch 403 ^/env.php.*?$
RedirectMatch 403 ^/env.php
RedirectMatch 403 ^/env.php$
RedirectMatch 403 ^/config.php$
RedirectMatch 403 ^/config.bak.php$
RedirectMatch 403 ^/Makefile
RedirectMatch 403 ^/package.json
RedirectMatch 403 ^/package-lock.json

View File

@@ -2,7 +2,7 @@ FROM php:7.4-fpm-alpine
WORKDIR /var/www/
RUN apk add gmp-dev icu-dev zlib-dev libpng-dev
RUN apk add gmp-dev
RUN curl --silent --show-error https://getcomposer.org/installer | php
# Copy any config files in
@@ -12,9 +12,7 @@ RUN ln -sf /dev/stderr /var/log/fpm-error.log
RUN docker-php-ext-install \
calendar \
intl \
pdo_mysql \
gd \
gmp \
opcache && \
docker-php-ext-enable pdo_mysql opcache
@@ -27,6 +25,4 @@ RUN php composer.phar install \
--no-scripts \
--prefer-dist
RUN chown -R www-data:www-data /var/www
EXPOSE 9000

View File

@@ -1,3 +1,5 @@
BSD 3-Clause License
Copyright (c) 2017, phpvms - http://www.phpvms.net
All rights reserved.
@@ -15,9 +17,6 @@ modification, are permitted provided that the following conditions are met:
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
* A "powered by phpvms" is required in page footers, unless the license has
purchased to omit it.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE

View File

@@ -82,6 +82,10 @@ test:
phpcs:
@vendor/bin/php-cs-fixer fix --config=.php_cs -v --diff --diff-format=udiff --dry-run
#.PHONY: phpstan
#phpstan:
# vendor/bin/phpstan analyse -c phpstan.neon -v --level 2 app
.PHONY: replay-acars
replay-acars:
#@php artisan phpvms:replay AAL10,AAL3113,BAW172,DAL988,FIN6,MSR986 --manual
@@ -91,6 +95,11 @@ replay-acars:
sass-watch:
sass --watch public/assets/admin/sass/paper-dashboard.scss:public/assets/admin/css/paper-dashboard.css
.PHONY: schema
schema:
#php artisan infyom:scaffold Aircraft --fieldsFile=database/schema/aircraft.json
echo ""
.PHONY: deploy-package
deploy-package:
./.travis/deploy_script.sh
@@ -100,9 +109,17 @@ reset-installer:
@php artisan database:create --reset
@php artisan migrate:refresh --seed
.PHONY: docker-test
docker-test:
@docker-compose -f docker-compose.yml -f docker-compose.local.yml up
.PHONY: docker
docker:
@mkdir -p $(CURR_PATH)/tmp/mysql
-docker rm -f phpvms
docker build -t phpvms .
docker run --name=phpvms \
-v $(CURR_PATH):/var/www/ \
-v $(CURR_PATH)/tmp/mysql:/var/lib/mysql \
-p 8080:80 \
phpvms
.PHONY: docker-clean
docker-clean:

View File

@@ -30,16 +30,15 @@ A full distribution, with all of the composer dependencies, is available at this
[View installation details](https://docs.phpvms.net/installation/installation)
## Development Environment with Docker
## Development Environment
A full development environment can be brought up using Docker, without having to install composer/npm locally
A full development environment can be brought up using Docker:
```bash
make docker-test
# **OR** with docker-compose directly
docker-compose -f docker-compose.yml -f docker-compose.local.yml up
composer install
npm install
docker-compose build
docker-compose up
```
Then go to `http://localhost`. If you're using dnsmasq, the `app` container is listening on `phpvms.test`, or you can add to your `/etc/hosts` file:
@@ -48,8 +47,6 @@ Then go to `http://localhost`. If you're using dnsmasq, the `app` container is l
127.0.0.1 phpvms.test
```
The `docker-compose.local.yml` overrides the `app` section in `docker-compose.yml`. The standard `docker-compose.yml` can be used if you want to deploy from the image, or as a template for your own Dockerized deployments.
### Building JS/CSS assets
Yarn is required, run:

View File

@@ -4,9 +4,9 @@ namespace App\Console\Commands;
use App;
use App\Contracts\Command;
use App\Services\Installer\ConfigService;
use App\Services\Installer\SeederService;
use DatabaseSeeder;
use Modules\Installer\Services\ConfigService;
/**
* Create the config files
@@ -81,13 +81,13 @@ class CreateConfigs extends Command
$this->info('Regenerating the config files');
$cfgSvc->createConfigFiles([
'APP_ENV' => 'dev',
'SITE_NAME' => $this->argument('name'),
'DB_CONNECTION' => 'mysql',
'DB_HOST' => $this->argument('db_host'),
'DB_DATABASE' => $this->argument('db_name'),
'DB_USERNAME' => $this->argument('db_user'),
'DB_PASSWORD' => $this->argument('db_pass'),
'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!');

View File

@@ -79,9 +79,9 @@ class DevInstall extends Command
$this->info('Regenerating the config files');
$cfgSvc->createConfigFiles([
'APP_ENV' => 'dev',
'SITE_NAME' => 'phpvms test',
'DB_CONNECTION' => 'sqlite',
'APP_ENV' => 'dev',
'SITE_NAME' => 'phpvms test',
'DB_CONN' => 'sqlite',
]);
$this->info('Config files generated!');

View File

@@ -1,32 +0,0 @@
<?php
namespace App\Console\Commands;
use App;
use App\Contracts\Command;
class EmailTest extends Command
{
protected $signature = 'phpvms:email-test';
protected $description = 'Send a test notification to admins';
/**
* Run dev related commands
*
* @throws \Symfony\Component\HttpFoundation\File\Exception\FileException
*/
public function handle()
{
/** @var App\Notifications\NotificationEventsHandler $eventHandler */
$eventHandler = app(App\Notifications\NotificationEventsHandler::class);
$news = new App\Models\News();
$news->user_id = 1;
$news->subject = 'Test News';
$news->body = 'Test Body';
$news->save();
$newsEvent = new App\Events\NewsAdded($news);
$eventHandler->onNewsAdded($newsEvent);
}
}

View File

@@ -1,38 +0,0 @@
<?php
namespace App\Console\Commands;
use App;
use App\Contracts\Command;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Log;
class ProcessQueue extends Command
{
protected $signature = 'queue:cron';
protected $description = 'Process the queue from a cron job';
/**
* Run the queue tasks
*/
public function handle()
{
Artisan::call('queue:work', [
'--sansdaemon' => null,
'--stop-when-empty' => null,
]);
Log::info(Artisan::output());
///** @var App\Support\WorkCommand $queueWorker */
//$queueWorker = new App\Support\WorkCommand(app('queue.worker'), app('cache.store'));
//$queueWorker->setInput($queueWorker->createInputFromArguments([]));
//$queueWorker->handle();
/*$output = $this->call('queue:work', [
'--stop-when-empty' => null,
]);
Log::info($output);*/
}
}

View File

@@ -1,25 +0,0 @@
<?php
namespace App\Console\Commands;
use App\Contracts\Command;
use App\Services\Installer\ConfigService;
/**
* Command to rewrite the config files
*/
class RewriteConfigs extends Command
{
protected $signature = 'phpvms:rewrite-configs';
protected $description = 'Rewrite the config files';
/**
* Run dev related commands
*/
public function handle()
{
/** @var ConfigService $configSvc */
$configSvc = app(ConfigService::class);
$configSvc->rewriteConfigFiles();
}
}

View File

@@ -1,25 +0,0 @@
<?php
namespace App\Console\Cron;
use App\Contracts\Command;
use Illuminate\Support\Facades\Artisan;
/**
* This just calls the CronHourly event, so all of the
* listeners, etc can just be called to run those tasks
*/
class JobQueue extends Command
{
protected $signature = 'cron:queue';
protected $description = 'Run the cron queue tasks';
protected $schedule;
public function handle(): void
{
$this->redirectLoggingToFile('cron');
Artisan::call('queue:cron');
$this->info(Artisan::output());
}
}

View File

@@ -3,7 +3,6 @@
namespace App\Console;
use App\Console\Cron\Hourly;
use App\Console\Cron\JobQueue;
use App\Console\Cron\Monthly;
use App\Console\Cron\Nightly;
use App\Console\Cron\Weekly;
@@ -26,13 +25,6 @@ class Kernel extends ConsoleKernel
*/
protected function schedule(Schedule $schedule): void
{
// If not using the queue worker then run those via cron
if (!config('queue.worker', false)) {
$schedule->command(JobQueue::class)
->everyMinute()
->withoutOverlapping();
}
$schedule->command(Nightly::class)->dailyAt('01:00');
$schedule->command(Weekly::class)->weeklyOn(0);
$schedule->command(Monthly::class)->monthlyOn(1);

View File

@@ -24,9 +24,9 @@ abstract class Command extends \Illuminate\Console\Command
parent::__construct();
// Running in the console but not in the tests
/*if (app()->runningInConsole() && env('APP_ENV') !== 'testing') {
if (app()->runningInConsole() && env('APP_ENV') !== 'testing') {
$this->redirectLoggingToFile('stdout');
}*/
}
}
/**

View File

@@ -170,11 +170,6 @@ class ImportExport
}
foreach ($split_values as $value) {
$value = trim($value);
if ($value === '') {
continue;
}
// This isn't in the query string format, so it's
// just a straight key-value pair set
if (strpos($value, '?') === false) {

View File

@@ -2,9 +2,9 @@
namespace App\Contracts;
use App\Notifications\Channels\Discord\DiscordMessage;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Support\Facades\Log;
class Notification extends \Illuminate\Notifications\Notification implements ShouldQueue
{
@@ -17,14 +17,14 @@ class Notification extends \Illuminate\Notifications\Notification implements Sho
{
// Look in the notifications.channels config and see where this particular
// notification can go. Map it to $channels
/*$klass = static::class;
$klass = static::class;
$notif_config = config('notifications.channels', []);
if (!array_key_exists($klass, $notif_config)) {
Log::error('Notification type '.$klass.' missing from notifications config, defaulting to mail');
return;
}
$this->channels = $notif_config[$klass];*/
$this->channels = $notif_config[$klass];
}
/**
@@ -34,16 +34,8 @@ class Notification extends \Illuminate\Notifications\Notification implements Sho
*
* @return array
*/
/*public function via($notifiable)
public function via($notifiable)
{
return $this->channels;
}*/
/**
* @return DiscordMessage|null
*/
public function toDiscordChannel($notifiable): ?DiscordMessage
{
return null;
}
}

View File

@@ -2,14 +2,11 @@
namespace App\Contracts;
use Exception;
use Illuminate\Validation\Validator;
use function is_array;
use Prettus\Repository\Eloquent\BaseRepository;
use Prettus\Repository\Exceptions\RepositoryException;
/**
* @mixin BaseRepository
* @mixin \Prettus\Repository\Eloquent\BaseRepository
*/
abstract class Repository extends BaseRepository
{
@@ -23,8 +20,8 @@ abstract class Repository extends BaseRepository
{
try {
return $this->find($id, $columns);
} catch (Exception $e) {
return null;
} catch (\Exception $e) {
return;
}
}
@@ -35,7 +32,11 @@ abstract class Repository extends BaseRepository
*/
public function validate($values)
{
$validator = Validator::make($values, $this->model()->rules);
$validator = Validator::make(
$values,
$this->model()->rules
);
if ($validator->fails()) {
return $validator->messages();
}
@@ -49,8 +50,6 @@ abstract class Repository extends BaseRepository
* @param int $count
* @param string $sort_by created_at (default) or updated_at
*
* @throws RepositoryException
*
* @return mixed
*/
public function recent($count = null, $sort_by = 'created_at')
@@ -72,7 +71,7 @@ abstract class Repository extends BaseRepository
return $this->scopeQuery(function ($query) use ($where, $sort_by, $order_by) {
$q = $query->where($where);
// See if there are multi-column sorts
if (is_array($sort_by)) {
if (\is_array($sort_by)) {
foreach ($sort_by as $key => $sort) {
$q = $q->orderBy($key, $sort);
}
@@ -99,7 +98,7 @@ abstract class Repository extends BaseRepository
return $this->scopeQuery(function ($query) use ($col, $values, $sort_by, $order_by) {
$q = $query->whereNotIn($col, $values);
// See if there are multi-column sorts
if (is_array($sort_by)) {
if (\is_array($sort_by)) {
foreach ($sort_by as $key => $sort) {
$q = $q->orderBy($key, $sort);
}
@@ -119,7 +118,7 @@ abstract class Repository extends BaseRepository
* @param array $columns
* @param string $method
*
* @throws RepositoryException
* @throws \Prettus\Repository\Exceptions\RepositoryException
*
* @return mixed
*/

View File

@@ -2,10 +2,7 @@
namespace App\Contracts;
use App\Support\Resources\CustomAnonymousResourceCollection;
use App\Support\Resources\CustomPaginatedResourceResponse;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Pagination\AbstractPaginator;
/**
* Base class for a resource/response
@@ -29,28 +26,4 @@ class Resource extends JsonResource
}
}
}
/**
* Customize the response to exclude all the extra data that isn't used. Based on:
* https://gist.github.com/derekphilipau/4be52164a69ce487dcd0673656d280da
*
* @param \Illuminate\Http\Request $request
*
* @return \Illuminate\Http\JsonResponse
*/
public function toResponse($request)
{
return $this->resource instanceof AbstractPaginator
? (new CustomPaginatedResourceResponse($this))->toResponse($request)
: parent::toResponse($request);
}
public static function collection($resource)
{
return tap(new CustomAnonymousResourceCollection($resource, static::class), function ($collection) {
if (property_exists(static::class, 'preserveKeys')) {
$collection->preserveKeys = (new static([]))->preserveKeys === true;
}
});
}
}

View File

@@ -5,7 +5,6 @@ namespace App\Cron\Hourly;
use App\Contracts\Listener;
use App\Events\CronHourly;
use App\Models\Enums\PirepState;
use App\Models\Enums\PirepStatus;
use App\Models\Pirep;
use App\Services\PirepService;
use Carbon\Carbon;
@@ -18,7 +17,7 @@ use Illuminate\Support\Facades\Log;
class DeletePireps extends Listener
{
/**
* Delete old rejected PIREPs
* Remove expired bids
*
* @param CronHourly $event
*
@@ -38,11 +37,8 @@ class DeletePireps extends Listener
*/
protected function deletePireps(int $expire_time_hours, int $state)
{
$dt = Carbon::now('UTC')->subHours($expire_time_hours);
$pireps = Pirep::where('created_at', '<', $dt)
->where(['state' => $state])
->where('status', '<>', PirepStatus::PAUSED)
->get();
$dt = Carbon::now()->subHours($expire_time_hours);
$pireps = Pirep::whereDate('created_at', '<', $dt)->where(['state' => $state])->get();
/** @var PirepService $pirepSvc */
$pirepSvc = app(PirepService::class);

View File

@@ -25,7 +25,7 @@ class RemoveExpiredBids extends Listener
return;
}
$date = Carbon::now('UTC')->subHours(setting('bids.expire_time'));
Bid::where('created_at', '<', $date)->delete();
$date = Carbon::now()->subHours(setting('bids.expire_time'));
Bid::whereDate('created_at', '<', $date)->delete();
}
}

View File

@@ -4,11 +4,9 @@ namespace App\Cron\Hourly;
use App\Contracts\Listener;
use App\Events\CronHourly;
use App\Events\PirepCancelled;
use App\Models\Enums\PirepState;
use App\Models\Pirep;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
/**
* Remove expired live flights
@@ -28,15 +26,9 @@ class RemoveExpiredLiveFlights extends Listener
return;
}
$date = Carbon::now('UTC')->subHours(setting('acars.live_time'));
$pireps = Pirep::where('updated_at', '<', $date)
$date = Carbon::now()->subHours(setting('acars.live_time'));
Pirep::whereDate('updated_at', '<', $date)
->where('state', PirepState::IN_PROGRESS)
->get();
foreach ($pireps as $pirep) {
event(new PirepCancelled($pirep));
Log::info('Cron: Deleting Expired Live PIREP id='.$pirep->id.', state='.PirepState::label($pirep->state));
$pirep->delete();
}
->delete();
}
}

View File

@@ -1,9 +1,9 @@
<?php
namespace App\Cron\Hourly;
namespace App\Cron\Nightly;
use App\Contracts\Listener;
use App\Events\CronHourly;
use App\Events\CronNightly;
use App\Services\SimBriefService;
use Illuminate\Support\Facades\Log;
@@ -22,9 +22,9 @@ class ClearExpiredSimbrief extends Listener
/**
* @param \App\Events\CronNightly $event
*/
public function handle(CronHourly $event): void
public function handle(CronNightly $event): void
{
Log::info('Hourly: Removing expired Simbrief entries');
Log::info('Nightly: Removing expired Simbrief entries');
$this->simbriefSvc->removeExpiredEntries();
}
}

View File

@@ -7,6 +7,9 @@ use App\Events\CronNightly;
use App\Services\VersionService;
use Illuminate\Support\Facades\Log;
/**
* Determine if any pilots should be set to ON LEAVE status
*/
class NewVersionCheck extends Listener
{
private $versionSvc;

View File

@@ -11,7 +11,7 @@ if (!function_exists('createFactoryICAO')) {
$characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
$max = strlen($characters) - 1;
$string = '';
for ($i = 0; $i < 5; $i++) {
for ($i = 0; $i < 4; $i++) {
try {
$string .= $characters[random_int(0, $max)];
} catch (Exception $e) {

View File

@@ -1,20 +1,17 @@
<?php
use App\Models\Journal;
use Carbon\Carbon;
use Faker\Generator as Faker;
use Ramsey\Uuid\Uuid;
$factory->define(App\Models\JournalTransaction::class, function (Faker $faker) {
$factory->define(App\Models\JournalTransactions::class, function (Faker $faker) {
return [
'transaction_group' => Uuid::uuid4()->toString(),
'transaction_group' => \Ramsey\Uuid\Uuid::uuid4()->toString(),
'journal_id' => function () {
return factory(Journal::class)->create()->id;
return factory(\App\Models\Journal::class)->create()->id;
},
'credit' => $faker->numberBetween(100, 10000),
'debit' => $faker->numberBetween(100, 10000),
'currency' => 'USD',
'memo' => $faker->sentence(6),
'post_date' => Carbon::now('UTC'),
'post_date' => \Carbon\Carbon::now(),
];
});

View File

@@ -1,13 +0,0 @@
<?php
use Faker\Generator as Faker;
$factory->define(App\Models\Role::class, function (Faker $faker) {
return [
'id' => null,
'name' => $faker->name,
'display_name' => $faker->name,
'read_only' => false,
'disable_activity_checks' => $faker->boolean(),
];
});

View File

@@ -1,34 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddDisableactivitychecksToRoles extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('roles', function (Blueprint $table) {
$table->boolean('disable_activity_checks')
->default(false)
->after('read_only');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('roles', function (Blueprint $table) {
$table->dropColumn('disable_activity_checks');
});
}
}

View File

@@ -1,19 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\DB;
class RemoveSettingRemoveBidOnAccept extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
DB::table('settings')
->where(['key' => 'pireps.remove_bid_on_accept'])
->delete();
}
}

View File

@@ -1,30 +0,0 @@
<?php
use App\Contracts\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
/**
* Add a `anumeric_callsign` column for Alphanumeric Callsign to be assigned for a flight
* Exp DLH78BF, THY8EA, OGE1978
* According to FAA and EASA, callsigns must be maximum 7 chars in which first 3 chars is
* airline ICAO code remaining rest can be used freely according to airline's choices
*/
class FlightsAddAlphanumericCallsign extends Migration
{
public function up()
{
Schema::table('flights', function (Blueprint $table) {
$table->string('callsign', 4)
->nullable()
->after('flight_number');
});
}
public function down()
{
Schema::table('flights', function (Blueprint $table) {
$table->dropColumn('callsign');
});
}
}

View File

@@ -1,21 +0,0 @@
<?php
use App\Contracts\Migration;
use App\Services\Installer\ConfigService;
/**
* Migrate the configuration files
*/
class MigrateConfigs extends Migration
{
public function up()
{
/** @var ConfigService $configSvc */
$configSvc = app(ConfigService::class);
$configSvc->rewriteConfigFiles();
}
public function down()
{
}
}

View File

@@ -1,26 +0,0 @@
<?php
use App\Contracts\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
/**
* Increase Airport ICAO size to 5 chars
* https://github.com/nabeelio/phpvms/issues/1052
*/
class IncreaseIcaoSizes extends Migration
{
public function up()
{
Schema::table('airports', function (Blueprint $table) {
$table->string('iata', 5)->change();
$table->string('icao', 5)->change();
});
Schema::table('pireps', function (Blueprint $table) {
$table->string('dpt_airport_id', 5)->change();
$table->string('arr_airport_id', 5)->change();
$table->string('alt_airport_id', 5)->change();
});
}
}

View File

@@ -1,19 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\DB;
class RemoveSettingSimbriefExpireDays extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
DB::table('settings')
->where(['key' => 'simbrief.expire_days'])
->delete();
}
}

View File

@@ -1,32 +0,0 @@
<?php
use App\Contracts\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
class DiscordFields extends Migration
{
public function up()
{
// Delete the old Discord fields and then a webhook will get added
DB::table('settings')
->where(['key' => 'notifications.discord_api_key'])
->delete();
DB::table('settings')
->where(['key' => 'notifications.discord_public_channel_id'])
->delete();
DB::table('settings')
->where(['key' => 'notifications.discord_public_channel_id'])
->delete();
// Add a field to the user to enter their own Discord ID
Schema::table('users', function (Blueprint $table) {
$table->string('discord_id')
->default('')
->after('rank_id');
});
}
}

View File

@@ -1,18 +0,0 @@
<?php
use App\Contracts\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class DiscordPrivateChannelId extends Migration
{
public function up()
{
// Add a field to the user to enter their own Discord ID
Schema::table('users', function (Blueprint $table) {
$table->string('discord_private_channel_id')
->default('')
->after('discord_id');
});
}
}

View File

@@ -1,5 +1,519 @@
acars:
- pirep_id: b68R5gwVzpVe
- id: aM8QpMPEB15e
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
name: null
log: null
lat: '17.934117958358'
lon: '-76.77856721815'
heading: '124'
altitude: '8.1663703232199'
vs: '0'
gs: '0.0064996252497234'
transponder: null
autopilot: null
fuel_flow: null
sim_time: now
created_at: 'now'
updated_at: 'now'
- id: eZ6VJ3xj8vge
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
name: null
log: null
lat: '17.934117498661'
lon: '-76.778566516289'
heading: '124'
altitude: '8.1664622222087'
vs: '0'
gs: '0'
transponder: null
autopilot: null
fuel_flow: null
sim_time: now
created_at: 'now'
updated_at: 'now'
- id: bo2QqDLl2lLa
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
name: null
log: null
lat: '17.933884143334'
lon: '-76.778210172233'
heading: '124'
altitude: '8.1707802663933'
vs: '0'
gs: '14.419195209695'
transponder: null
autopilot: null
fuel_flow: null
sim_time: now
created_at: 'now'
updated_at: 'now'
- id: aM8QpM4qV2Be
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
name: null
log: null
lat: '17.933705349611'
lon: '-76.777936938059'
heading: '124'
altitude: '8.170089899507'
vs: '0'
gs: '15.392330039049'
transponder: null
autopilot: null
fuel_flow: null
sim_time: now
created_at: 'now'
updated_at: 'now'
- id: dR6oxR9qjoOd
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
name: null
log: null
lat: '17.933130691906'
lon: '-76.777152737985'
heading: '158'
altitude: '8.1683570286331'
vs: '0'
gs: '10.450467475023'
transponder: null
autopilot: null
fuel_flow: null
sim_time: now
created_at: 'now'
updated_at: 'now'
- id: erkRwJODRvEa
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
name: null
log: null
lat: '17.932580370289'
lon: '-76.777450200122'
heading: '221'
altitude: '8.1695896791822'
vs: '0'
gs: '12.932334300694'
transponder: null
autopilot: null
fuel_flow: null
sim_time: now
created_at: 'now'
updated_at: 'now'
- id: b2kv53VMy7Ad
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
name: null
log: null
lat: '17.932012550651'
lon: '-76.778009113329'
heading: '296'
altitude: '8.1683852467213'
vs: '0'
gs: '10.502719192825'
transponder: null
autopilot: null
fuel_flow: null
sim_time: now
created_at: 'now'
updated_at: 'now'
- id: eXDoE14JxAve
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
name: null
log: null
lat: '17.932052237309'
lon: '-76.778111495187'
heading: '290'
altitude: '8.1719753739837'
vs: '0'
gs: '12.643743277153'
transponder: null
autopilot: null
fuel_flow: null
sim_time: now
created_at: 'now'
updated_at: 'now'
- id: b68R5gZ5YyOe
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
name: null
log: null
lat: '17.932664026837'
lon: '-76.779705339967'
heading: '293'
altitude: '8.2203963962548'
vs: '0'
gs: '64.870244840054'
transponder: null
autopilot: null
fuel_flow: null
sim_time: now
created_at: 'now'
updated_at: 'now'
- id: bqxYvGNN5N0a
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
name: null
log: null
lat: '17.934300220408'
lon: '-76.783954914814'
heading: '293'
altitude: '8.3302468103811'
vs: '0'
gs: '122.78529244208'
transponder: null
autopilot: null
fuel_flow: null
sim_time: now
created_at: 'now'
updated_at: 'now'
- id: en5rpBKw514d
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
name: null
log: null
lat: '17.935736496556'
lon: '-76.78765616448'
heading: '293'
altitude: '49.554739665916'
vs: '21'
gs: '146.79677958636'
transponder: null
autopilot: null
fuel_flow: null
sim_time: now
created_at: 'now'
updated_at: 'now'
- id: erkRwJA29l2a
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
name: null
log: null
lat: '17.976972983585'
lon: '-76.896548114872'
heading: '297'
altitude: '6228.684012199'
vs: '62'
gs: '281.03976876098'
transponder: null
autopilot: null
fuel_flow: null
sim_time: now
created_at: 'now'
updated_at: 'now'
- id: dR6oxR3r5nwd
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
name: null
log: null
lat: '18.061360208405'
lon: '-77.056156629983'
heading: '301'
altitude: '12522.331716891'
vs: '25'
gs: '371.70833265547'
transponder: null
autopilot: null
fuel_flow: null
sim_time: now
created_at: 'now'
updated_at: 'now'
- id: e1wr82J877Zb
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
name: null
log: null
lat: '18.17373613295'
lon: '-77.260347185993'
heading: '301'
altitude: '16802.15636323'
vs: '43'
gs: '421.37353688139'
transponder: null
autopilot: null
fuel_flow: null
sim_time: now
created_at: 'now'
updated_at: 'now'
- id: bqxYvGyExN2a
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
name: null
log: null
lat: '18.193907285814'
lon: '-77.29810465405'
heading: '297'
altitude: '17395.953175647'
vs: '40'
gs: '425.98105291451'
transponder: null
autopilot: null
fuel_flow: null
sim_time: now
created_at: 'now'
updated_at: 'now'
- id: aQW0wQDQk5Md
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
name: null
log: null
lat: '18.648921231143'
lon: '-78.014696613517'
heading: '323'
altitude: '37108.124381987'
vs: '22'
gs: '438.52028383384'
transponder: null
autopilot: null
fuel_flow: null
sim_time: now
created_at: 'now'
updated_at: 'now'
- id: e9rQ5lk3p63a
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
name: null
log: null
lat: '18.796585259338'
lon: '-78.194734005052'
heading: '260'
altitude: '39718.178225504'
vs: '19'
gs: '432.41969107334'
transponder: null
autopilot: null
fuel_flow: null
sim_time: now
created_at: 'now'
updated_at: 'now'
- id: aQW0wQP8vZqd
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
name: null
log: null
lat: '18.660552760063'
lon: '-78.407597067994'
heading: '242'
altitude: '40998.775690971'
vs: '-25'
gs: '449.51695639627'
transponder: null
autopilot: null
fuel_flow: null
sim_time: now
created_at: 'now'
updated_at: 'now'
- id: bqxYvGKgp32a
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
name: null
log: null
lat: '18.592775999582'
lon: '-78.638711340118'
heading: '298'
altitude: '41060.297106821'
vs: '0'
gs: '427.14806185954'
transponder: null
autopilot: null
fuel_flow: null
sim_time: now
created_at: 'now'
updated_at: 'now'
- id: bqxYvGg2r02a
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
name: null
log: null
lat: '18.718367591656'
lon: '-78.840980459275'
heading: '284'
altitude: '41065.55293844'
vs: '1'
gs: '424.89060056552'
transponder: null
autopilot: null
fuel_flow: null
sim_time: now
created_at: 'now'
updated_at: 'now'
- id: e0RV61wPj53b
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
name: null
log: null
lat: '18.77448809677'
lon: '-79.082727467209'
heading: '283'
altitude: '41069.809333539'
vs: '0'
gs: '425.02780492483'
transponder: null
autopilot: null
fuel_flow: null
sim_time: now
created_at: 'now'
updated_at: 'now'
- id: dwpmBOo3wWwe
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
name: null
log: null
lat: '18.813031600863'
lon: '-79.249543355636'
heading: '283'
altitude: '41072.545805172'
vs: '0'
gs: '425.04687332464'
transponder: null
autopilot: null
fuel_flow: null
sim_time: now
created_at: 'now'
updated_at: 'now'
- id: ejRqlxXoZPle
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
name: null
log: null
lat: '18.840653974635'
lon: '-79.370042672541'
heading: '283'
altitude: '40396.200981621'
vs: '-16'
gs: '428.08364925851'
transponder: null
autopilot: null
fuel_flow: null
sim_time: now
created_at: 'now'
updated_at: 'now'
- id: eVOPBYw4q9Xa
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
name: null
log: null
lat: '18.868358744495'
lon: '-79.491434926253'
heading: '283'
altitude: '39399.093383161'
vs: '-16'
gs: '427.57826037174'
transponder: null
autopilot: null
fuel_flow: null
sim_time: now
created_at: 'now'
updated_at: 'now'
- id: aOYyrOmVPzEd
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
name: null
log: null
lat: '18.896191929474'
lon: '-79.613169477385'
heading: '284'
altitude: '36491.730092364'
vs: '-55'
gs: '429.74732238829'
transponder: null
autopilot: null
fuel_flow: null
sim_time: now
created_at: 'now'
updated_at: 'now'
- id: dL98oLQgyzje
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
name: null
log: null
lat: '18.9242378342'
lon: '-79.736368411294'
heading: '284'
altitude: '32998.644142986'
vs: '-61'
gs: '434.90864533098'
transponder: null
autopilot: null
fuel_flow: null
sim_time: now
created_at: 'now'
updated_at: 'now'
- id: e9rQ5lqD2o8a
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
name: null
log: null
lat: '18.952608029755'
lon: '-79.861339775352'
heading: '284'
altitude: '29069.168636089'
vs: '-68'
gs: '441.90475491564'
transponder: null
autopilot: null
fuel_flow: null
sim_time: now
created_at: 'now'
updated_at: 'now'
- id: av2oANWY1vma
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
@@ -36,7 +550,8 @@ acars:
sim_time: now
created_at: 'now'
updated_at: 'now'
- pirep_id: b68R5gwVzpVe
- id: e1wr82gp8zGb
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
@@ -54,7 +569,8 @@ acars:
sim_time: now
created_at: 'now'
updated_at: 'now'
- pirep_id: b68R5gwVzpVe
- id: dG65jDL2gK0b
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
@@ -72,7 +588,8 @@ acars:
sim_time: now
created_at: 'now'
updated_at: 'now'
- pirep_id: b68R5gwVzpVe
- id: epYQ0ENmyvXa
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
@@ -90,7 +607,8 @@ acars:
sim_time: now
created_at: 'now'
updated_at: 'now'
- pirep_id: b68R5gwVzpVe
- id: erkRwJPrVoEa
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
@@ -108,7 +626,8 @@ acars:
sim_time: now
created_at: 'now'
updated_at: 'now'
- pirep_id: b68R5gwVzpVe
- id: e1wr82gZXqZb
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
@@ -126,7 +645,8 @@ acars:
sim_time: now
created_at: 'now'
updated_at: 'now'
- pirep_id: b68R5gwVzpVe
- id: eER95AJ4XLga
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
@@ -144,7 +664,8 @@ acars:
sim_time: now
created_at: 'now'
updated_at: 'now'
- pirep_id: b68R5gwVzpVe
- id: dPNZvP0O0Gza
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
@@ -162,7 +683,8 @@ acars:
sim_time: now
created_at: 'now'
updated_at: 'now'
- pirep_id: b68R5gwVzpVe
- id: aQW0wQYVm2Yd
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
@@ -180,7 +702,8 @@ acars:
sim_time: now
created_at: 'now'
updated_at: 'now'
- pirep_id: b68R5gwVzpVe
- id: eXDoE11x32We
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'

File diff suppressed because one or more lines are too long

View File

@@ -54,13 +54,6 @@
options: ''
type: text
description: 'Enter your Google Analytics Tracking ID'
- key: general.record_user_ip
name: 'Record user IP address'
group: general
value: true
options: ''
type: boolean
description: Record the user's IP address on register/login
- key: units.currency
name: 'Currency'
group: units
@@ -151,20 +144,6 @@
options:
type: text
description: If an airport's Jet A Fuel Cost isn't added, set this value by default
- key: airports.default_100ll_fuel_cost
name: 'Default 100LL Fuel Cost'
group: airports
value: 0.9
options:
type: text
description: If an airport's 100LL Fuel Cost isn't added, set this value by default
- key: airports.default_mogas_fuel_cost
name: 'Default MOGAS Fuel Cost'
group: airports
value: 0.8
options:
type: text
description: If an airport's MOGAS Fuel Cost isn't added, set this value by default
- key: bids.disable_flight_on_bid
name: 'Disable flight on bid'
group: bids
@@ -214,13 +193,13 @@
options: ''
type: boolean
description: 'Only allow briefs to be created for bidded flights'
- key: simbrief.expire_hours
- key: simbrief.expire_days
name: 'Simbrief Expire Time'
group: simbrief
value: 6
value: 5
options: ''
type: number
description: 'Hours after how long to remove unused briefs'
description: 'Days after how long to remove unused briefs'
- key: simbrief.noncharter_pax_weight
name: 'Non-Charter Passenger Weight'
group: simbrief
@@ -256,20 +235,6 @@
options: ''
type: boolean
description: 'Use pilot ident as Simbrief ATC Callsign'
- key: simbrief.name_private
name: 'Use Privatized Name at OFPs'
group: simbrief
value: false
options: ''
type: boolean
description: 'Use privatized user name as SimBrief OFP captain name'
- key: simbrief.block_aircraft
name: 'Restrict Aircraft'
group: simbrief
value: false
options: ''
type: boolean
description: 'When enabled, an aircraft can only be used for one active SimBrief OFP and Flight/Pirep'
- key: pireps.duplicate_check_time
name: 'PIREP duplicate time check'
group: pireps
@@ -291,6 +256,13 @@
options: ''
type: boolean
description: 'Only allow aircraft that are at the departure airport'
- key: pireps.remove_bid_on_accept
name: 'Remove bid on accept'
group: pireps
value: false
options: ''
type: boolean
description: 'When a PIREP is accepted, remove the bid, if it exists'
- key: pireps.advanced_fuel
name: 'Advanced Fuel Calculations'
group: pireps
@@ -375,20 +347,20 @@
options: ''
type: boolean
description: 'Count transfer hours in calculations, like ranks and the total hours'
- key: notifications.discord_public_webhook_url
name: Discord Public Webhook URL
- key: notifications.discord_api_key
name: Discord API token
group: notifications
value: ''
options: ''
type: text
description: The Discord Webhook URL for public notifications
- key: notifications.discord_private_webhook_url
name: Discord Private Webhook URL
group: notifications
description: Discord API token for notifications
- key: 'notifications.discord_public_channel_id'
name: 'Discord Public Channel ID'
group: 'notifications'
value: ''
options: ''
type: text
description: The Discord Webhook URL for private notifications
type: 'text'
description: 'Discord public channel ID for broadcasat notifications'
- key: 'cron.random_id'
name: 'Cron Randomized ID'
group: 'cron'

View File

@@ -1,16 +0,0 @@
<?php
namespace App\Events;
use App\Contracts\Event;
use App\Models\Pirep;
class PirepStateChange extends Event
{
public $pirep;
public function __construct(Pirep $pirep)
{
$this->pirep = $pirep;
}
}

View File

@@ -1,19 +0,0 @@
<?php
namespace App\Events;
use App\Contracts\Event;
use App\Models\Pirep;
/**
* Status change like Boarding, Taxi, etc
*/
class PirepStatusChange extends Event
{
public $pirep;
public function __construct(Pirep $pirep)
{
$this->pirep = $pirep;
}
}

View File

@@ -1,38 +0,0 @@
<?php
namespace App\Exceptions;
use App\Models\Aircraft;
class AircraftNotAvailable extends AbstractHttpException
{
public const MESSAGE = 'The aircraft is not available for flight';
private $aircraft;
public function __construct(Aircraft $aircraft)
{
$this->aircraft = $aircraft;
parent::__construct(
400,
static::MESSAGE
);
}
public function getErrorType(): string
{
return 'aircraft-not-available';
}
public function getErrorDetails(): string
{
return $this->getMessage();
}
public function getErrorMetadata(): array
{
return [
'aircraft_id' => $this->aircraft->id,
];
}
}

View File

@@ -1,44 +0,0 @@
<?php
namespace App\Exceptions;
use App\Models\Pirep;
class PirepError extends AbstractHttpException
{
private $pirep;
private $error;
public function __construct(Pirep $pirep, string $error)
{
$this->error = $error;
$this->pirep = $pirep;
parent::__construct(400, $error);
}
/**
* Return the RFC 7807 error type (without the URL root)
*/
public function getErrorType(): string
{
return 'pirep-error';
}
/**
* Get the detailed error string
*/
public function getErrorDetails(): string
{
return $this->getMessage();
}
/**
* Return an array with the error details, merged with the RFC7807 response
*/
public function getErrorMetadata(): array
{
return [
'pirep_id' => $this->pirep->id,
];
}
}

View File

@@ -1,44 +0,0 @@
<?php
namespace App\Exceptions;
/**
* Prefile Error
*
* If listening to the prefile event message, use `throw new PrefileError("message message");`
* to abort the prefile process and send the message up to ACARS
*/
class PrefileError extends AbstractHttpException
{
private $error;
public function __construct(string $error)
{
$this->error = $error;
parent::__construct(400, $error);
}
/**
* Return the RFC 7807 error type (without the URL root)
*/
public function getErrorType(): string
{
return 'prefile-error';
}
/**
* Get the detailed error string
*/
public function getErrorDetails(): string
{
return $this->getMessage();
}
/**
* Return an array with the error details, merged with the RFC7807 response
*/
public function getErrorMetadata(): array
{
return [];
}
}

View File

@@ -1,38 +0,0 @@
<?php
namespace App\Exceptions;
class UserNotFound extends AbstractHttpException
{
public function __construct()
{
parent::__construct(
404,
'User not found'
);
}
/**
* Return the RFC 7807 error type (without the URL root)
*/
public function getErrorType(): string
{
return 'user-not-found';
}
/**
* Get the detailed error string
*/
public function getErrorDetails(): string
{
return $this->getMessage();
}
/**
* Return an array with the error details, merged with the RFC7807 response
*/
public function getErrorMetadata(): array
{
return [];
}
}

View File

@@ -115,7 +115,7 @@ class FlightController extends Controller
$avail_fleets = $all_aircraft->except($flight->subfleets->modelKeys());
foreach ($avail_fleets as $ac) {
$retval[$ac->id] = '['.$ac->airline->icao.']&nbsp;'.$ac->type.' - '.$ac->name;
$retval[$ac->id] = $ac->type.' - '.$ac->name;
}
return $retval;
@@ -152,7 +152,7 @@ class FlightController extends Controller
{
return view('admin.flights.create', [
'flight' => null,
'days' => 0,
'days' => [],
'flight_fields' => $this->flightFieldRepo->all(),
'airlines' => $this->airlineRepo->selectBoxList(),
'airports' => $this->airportRepo->selectBoxList(true, false),

View File

@@ -7,24 +7,29 @@ use App\Repositories\KvpRepository;
use App\Services\CronService;
use App\Services\VersionService;
use App\Support\Utils;
use Codedge\Updater\UpdaterManager;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Log;
use Laracasts\Flash\Flash;
use Nwidart\Modules\Facades\Module;
class MaintenanceController extends Controller
{
private $cronSvc;
private $kvpRepo;
private $updateManager;
private $versionSvc;
public function __construct(
CronService $cronSvc,
KvpRepository $kvpRepo,
UpdaterManager $updateManager,
VersionService $versionSvc
) {
$this->cronSvc = $cronSvc;
$this->kvpRepo = $kvpRepo;
$this->updateManager = $updateManager;
$this->versionSvc = $versionSvc;
}
@@ -101,6 +106,24 @@ class MaintenanceController extends Controller
return redirect(route('admin.maintenance.index'));
}
/**
* Update the phpVMS install
*
* @param \Illuminate\Http\Request $request
*
* @return mixed
*/
public function update(Request $request)
{
$new_version_tag = $this->kvpRepo->get('latest_version_tag');
Log::info('Attempting to update to '.$new_version_tag);
$module = Module::find('updater');
$module->enable();
return redirect('/update/downloader');
}
/**
* Enable the cron, or if it's enabled, change the ID that is used
*

View File

@@ -9,7 +9,6 @@ use Illuminate\Contracts\View\Factory;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Redirector;
use Illuminate\Support\Facades\Log;
use Illuminate\View\View;
class ModulesController extends Controller
@@ -30,7 +29,6 @@ class ModulesController extends Controller
{
$modules = $this->moduleSvc->getAllModules();
$new_modules = $this->moduleSvc->scan();
return view('admin.modules.index', [
'modules' => $modules,
'new_modules' => $new_modules,
@@ -99,14 +97,7 @@ class ModulesController extends Controller
*/
public function enable(Request $request)
{
$moduleName = $request->input('name');
try {
$this->moduleSvc->addModule($moduleName);
} catch (\Exception $e) {
Log::error('Error activating module '.$moduleName);
}
$this->moduleSvc->addModule($request->input('name'));
return redirect(route('admin.modules.index'));
}

View File

@@ -9,7 +9,6 @@ use App\Models\Enums\PirepSource;
use App\Models\Enums\PirepState;
use App\Models\Pirep;
use App\Models\PirepComment;
use App\Models\PirepFare;
use App\Repositories\AircraftRepository;
use App\Repositories\AirlineRepository;
use App\Repositories\AirportRepository;
@@ -101,7 +100,7 @@ class PirepController extends Controller
$tmp[$ac->id] = $ac['name'].' - '.$ac['registration'];
}
$aircraft[$subfleet->type] = $tmp;
$aircraft[$subfleet->name] = $tmp;
}
return $aircraft;
@@ -152,10 +151,10 @@ class PirepController extends Controller
$count = $request->input($field_name);
}
$fares[] = new PirepFare([
$fares[] = [
'fare_id' => $fare->id,
'count' => $count,
]);
];
}
$this->fareSvc->saveForPirep($pirep, $fares);

View File

@@ -6,12 +6,12 @@ use App\Contracts\Controller;
use App\Http\Requests\CreateUserRequest;
use App\Http\Requests\UpdateUserRequest;
use App\Models\Rank;
use App\Models\Role;
use App\Models\User;
use App\Models\UserAward;
use App\Repositories\AirlineRepository;
use App\Repositories\AirportRepository;
use App\Repositories\PirepRepository;
use App\Repositories\RoleRepository;
use App\Repositories\UserRepository;
use App\Services\UserService;
use App\Support\Timezonelist;
@@ -29,7 +29,6 @@ class UserController extends Controller
private $airlineRepo;
private $airportRepo;
private $pirepRepo;
private $roleRepo;
private $userRepo;
private $userSvc;
@@ -39,7 +38,6 @@ class UserController extends Controller
* @param AirlineRepository $airlineRepo
* @param AirportRepository $airportRepo
* @param PirepRepository $pirepRepo
* @param RoleRepository $roleRepo
* @param UserRepository $userRepo
* @param UserService $userSvc
*/
@@ -47,14 +45,12 @@ class UserController extends Controller
AirlineRepository $airlineRepo,
AirportRepository $airportRepo,
PirepRepository $pirepRepo,
RoleRepository $roleRepo,
UserRepository $userRepo,
UserService $userSvc
) {
$this->airlineRepo = $airlineRepo;
$this->airportRepo = $airportRepo;
$this->pirepRepo = $pirepRepo;
$this->roleRepo = $roleRepo;
$this->userSvc = $userSvc;
$this->userRepo = $userRepo;
}
@@ -92,7 +88,6 @@ class UserController extends Controller
->mapWithKeys(function ($item, $key) {
return [strtolower($item['alpha2']) => $item['name']];
});
$roles = $this->roleRepo->selectBoxList(false, true);
return view('admin.users.create', [
'user' => null,
@@ -103,7 +98,7 @@ class UserController extends Controller
'countries' => $countries,
'airports' => $airports,
'ranks' => Rank::all()->pluck('name', 'id'),
'roles' => $roles,
'roles' => Role::all()->pluck('name', 'id'),
]);
}
@@ -168,7 +163,6 @@ class UserController extends Controller
$airlines = $this->airlineRepo->selectBoxList();
$airports = $this->airportRepo->selectBoxList(false);
$roles = $this->roleRepo->selectBoxList(false, true);
return view('admin.users.edit', [
'user' => $user,
@@ -179,7 +173,7 @@ class UserController extends Controller
'airports' => $airports,
'airlines' => $airlines,
'ranks' => Rank::all()->pluck('name', 'id'),
'roles' => $roles,
'roles' => Role::all()->pluck('name', 'id'),
]);
}
@@ -258,12 +252,15 @@ class UserController extends Controller
public function destroy($id)
{
$user = $this->userRepo->findWithoutFail($id);
if (empty($user)) {
Flash::error('User not found');
return redirect(route('admin.users.index'));
}
$this->userSvc->removeUser($user);
$this->userRepo->delete($id);
Flash::success('User deleted successfully.');
return redirect(route('admin.users.index'));

View File

@@ -193,9 +193,9 @@ class AcarsController extends Controller
}
// Change the PIREP status if it's as SCHEDULED before
/*if ($pirep->status === PirepStatus::INITIATED) {
if ($pirep->status === PirepStatus::INITIATED) {
$pirep->status = PirepStatus::AIRBORNE;
}*/
}
$pirep->save();

View File

@@ -16,8 +16,9 @@ class AirlineController extends Controller
*
* @param AirlineRepository $airlineRepo
*/
public function __construct(AirlineRepository $airlineRepo)
{
public function __construct(
AirlineRepository $airlineRepo
) {
$this->airlineRepo = $airlineRepo;
}
@@ -30,9 +31,11 @@ class AirlineController extends Controller
*/
public function index(Request $request)
{
$airlines = $this->airlineRepo->whereOrder(['active' => true], 'name')->paginate();
$airports = $this->airlineRepo
->whereOrder(['active' => true], 'name', 'asc')
->paginate();
return AirlineResource::collection($airlines);
return AirlineResource::collection($airports);
}
/**

View File

@@ -3,6 +3,7 @@
namespace App\Http\Controllers\Api;
use App\Contracts\Controller;
use App\Events\PirepPrefiled;
use App\Events\PirepUpdated;
use App\Exceptions\AircraftPermissionDenied;
use App\Exceptions\PirepCancelled;
@@ -23,10 +24,10 @@ use App\Models\Enums\PirepFieldSource;
use App\Models\Enums\PirepSource;
use App\Models\Pirep;
use App\Models\PirepComment;
use App\Models\PirepFare;
use App\Models\PirepFieldValue;
use App\Repositories\AcarsRepository;
use App\Repositories\JournalRepository;
use App\Repositories\PirepRepository;
use App\Services\FareService;
use App\Services\Finance\PirepFinanceService;
use App\Services\PirepService;
use App\Services\UserService;
@@ -37,6 +38,8 @@ use Illuminate\Support\Facades\Log;
class PirepController extends Controller
{
private $acarsRepo;
private $fareSvc;
private $financeSvc;
private $journalRepo;
private $pirepRepo;
@@ -44,6 +47,8 @@ class PirepController extends Controller
private $userSvc;
/**
* @param AcarsRepository $acarsRepo
* @param FareService $fareSvc
* @param PirepFinanceService $financeSvc
* @param JournalRepository $journalRepo
* @param PirepRepository $pirepRepo
@@ -51,12 +56,16 @@ class PirepController extends Controller
* @param UserService $userSvc
*/
public function __construct(
AcarsRepository $acarsRepo,
FareService $fareSvc,
PirepFinanceService $financeSvc,
JournalRepository $journalRepo,
PirepRepository $pirepRepo,
PirepService $pirepSvc,
UserService $userSvc
) {
$this->acarsRepo = $acarsRepo;
$this->fareSvc = $fareSvc;
$this->financeSvc = $financeSvc;
$this->journalRepo = $journalRepo;
$this->pirepRepo = $pirepRepo;
@@ -93,7 +102,7 @@ class PirepController extends Controller
/**
* Check if a PIREP is cancelled
*
* @param Pirep $pirep
* @param $pirep
*
* @throws \App\Exceptions\PirepCancelled
*/
@@ -105,52 +114,50 @@ class PirepController extends Controller
}
/**
* @param $pirep
* @param Request $request
*
* @return PirepFieldValue[]
*/
protected function getFields(Request $request): ?array
protected function updateFields($pirep, Request $request)
{
if (!$request->filled('fields')) {
return [];
return;
}
$pirep_fields = [];
foreach ($request->input('fields') as $field_name => $field_value) {
$pirep_fields[] = new PirepFieldValue([
$pirep_fields[] = [
'name' => $field_name,
'value' => $field_value,
'source' => PirepFieldSource::ACARS,
]);
];
}
return $pirep_fields;
$this->pirepSvc->updateCustomFields($pirep->id, $pirep_fields);
}
/**
* Save the fares
*
* @param $pirep
* @param Request $request
*
* @throws \Exception
*
* @return PirepFare[]
*/
protected function getFares(Request $request): ?array
protected function updateFares($pirep, Request $request)
{
if (!$request->filled('fares')) {
return [];
return;
}
$fares = [];
foreach ($request->post('fares') as $fare) {
$fares[] = new PirepFare([
$fares[] = [
'fare_id' => $fare['id'],
'count' => $fare['count'],
]);
];
}
return $fares;
$this->fareSvc->saveForPirep($pirep, $fares);
}
/**
@@ -167,7 +174,6 @@ class PirepController extends Controller
'comments',
'flight',
'simbrief',
'position',
'user',
];
@@ -205,13 +211,16 @@ class PirepController extends Controller
$attrs = $this->parsePirep($request);
$attrs['source'] = PirepSource::ACARS;
$fields = $this->getFields($request);
$fares = $this->getFares($request);
$pirep = $this->pirepSvc->prefile($user, $attrs, $fields, $fares);
$pirep = $this->pirepSvc->prefile($user, $attrs);
Log::info('PIREP PREFILED');
Log::info($pirep->id);
$this->updateFields($pirep, $request);
$this->updateFares($pirep, $request);
event(new PirepPrefiled($pirep));
return $this->get($pirep->id);
}
@@ -252,9 +261,9 @@ class PirepController extends Controller
}
}
$fields = $this->getFields($request);
$fares = $this->getFares($request);
$pirep = $this->pirepSvc->update($pirep_id, $attrs, $fields, $fares);
$pirep = $this->pirepRepo->update($attrs, $pirep_id);
$this->updateFields($pirep, $request);
$this->updateFares($pirep, $request);
event(new PirepUpdated($pirep));
@@ -297,13 +306,11 @@ class PirepController extends Controller
}
try {
$fields = $this->getFields($request);
$fares = $this->getFares($request);
$pirep = $this->pirepSvc->file($pirep, $attrs, $fields, $fares);
$pirep = $this->pirepSvc->file($pirep, $attrs);
$this->updateFields($pirep, $request);
$this->updateFares($pirep, $request);
} catch (\Exception $e) {
Log::error($e);
throw $e;
}
// See if there there is any route data posted
@@ -405,8 +412,7 @@ class PirepController extends Controller
$pirep = Pirep::find($pirep_id);
$this->checkCancelled($pirep);
$fields = $this->getFields($request);
$this->pirepSvc->updateCustomFields($pirep_id, $fields);
$this->updateFields($pirep, $request);
return new PirepFieldCollection($pirep->fields);
}

View File

@@ -3,8 +3,6 @@
namespace App\Http\Controllers\Api;
use App\Contracts\Controller;
use App\Exceptions\Unauthorized;
use App\Exceptions\UserNotFound;
use App\Http\Resources\Bid as BidResource;
use App\Http\Resources\Pirep as PirepResource;
use App\Http\Resources\Subfleet as SubfleetResource;
@@ -93,10 +91,6 @@ class UserController extends Controller
public function get($id)
{
$user = $this->userSvc->getUser($id);
if ($user === null) {
throw new UserNotFound();
}
return new UserResource($user);
}
@@ -114,9 +108,6 @@ class UserController extends Controller
{
$user_id = $this->getUserId($request);
$user = $this->userSvc->getUser($user_id);
if ($user === null) {
throw new UserNotFound();
}
// Add a bid
if ($request->isMethod('PUT') || $request->isMethod('POST')) {
@@ -145,28 +136,6 @@ class UserController extends Controller
return BidResource::collection($bids);
}
/**
* Get a particular bid for a user
*
* @param $bid_id
* @param \Illuminate\Http\Request $request
*
* @return \App\Http\Resources\Bid
*/
public function get_bid($bid_id, Request $request)
{
/** @var \App\Models\User $user */
$user = Auth::user();
// Return the current bid
$bid = $this->bidSvc->getBid($user, $bid_id);
if ($bid->user_id !== $user->id) {
throw new Unauthorized(new \Exception('Bid not not belong to authenticated user'));
}
return new BidResource($bid);
}
/**
* Return the fleet that this user is allowed to
*
@@ -177,10 +146,6 @@ class UserController extends Controller
public function fleet(Request $request)
{
$user = $this->userRepo->find($this->getUserId($request));
if ($user === null) {
throw new UserNotFound();
}
$subfleets = $this->userSvc->getAllowableSubfleets($user);
return SubfleetResource::collection($subfleets);

View File

@@ -5,7 +5,6 @@ namespace App\Http\Controllers\Auth;
use App\Contracts\Controller;
use App\Exceptions\PilotIdNotFound;
use App\Models\Enums\UserState;
use App\Models\User;
use App\Services\UserService;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request;
@@ -105,16 +104,14 @@ class LoginController extends Controller
*/
protected function sendLoginResponse(Request $request)
{
/** @var User $user */
$user = Auth::user();
if (setting('general.record_user_ip', true)) {
$user->last_ip = $request->ip();
$user->save();
}
$user->last_ip = $request->ip();
$user->save();
if ($user->state !== UserState::ACTIVE && $user->state !== UserState::ON_LEAVE) {
Log::info('Trying to login '.$user->ident.', state '.UserState::label($user->state));
Log::info('Trying to login '.$user->ident.', state '
.UserState::label($user->state));
// Log them out
$this->guard()->logout();

View File

@@ -119,16 +119,11 @@ class RegisterController extends Controller
*
* @return User
*/
protected function create(Request $request): User
protected function create(array $opts)
{
// Default options
$opts = $request->all();
$opts['password'] = Hash::make($opts['password']);
if (setting('general.record_user_ip', true)) {
$opts['last_ip'] = $request->ip();
}
// Convert transfer hours into minutes
if (isset($opts['transfer_time'])) {
$opts['transfer_time'] *= 60;
@@ -163,7 +158,7 @@ class RegisterController extends Controller
{
$this->validator($request->all())->validate();
$user = $this->create($request);
$user = $this->create($request->all());
if ($user->state === UserState::PENDING) {
return view('auth.pending');
}

View File

@@ -36,8 +36,8 @@ class AirportController extends Controller
{
$id = strtoupper($id);
$airport = $this->airportRepo->where('id', $id)->first();
if (!$airport) {
$airport = $this->airportRepo->find($id);
if (empty($airport)) {
Flash::error('Airport not found!');
return redirect(route('frontend.dashboard.index'));
}
@@ -46,14 +46,12 @@ class AirportController extends Controller
->with(['dpt_airport', 'arr_airport', 'airline'])
->findWhere([
'arr_airport_id' => $id,
'active' => 1,
])->all();
$outbound_flights = $this->flightRepo
->with(['dpt_airport', 'arr_airport', 'airline'])
->findWhere([
'dpt_airport_id' => $id,
'active' => 1,
])->all();
return view('airports.show', [

View File

@@ -3,7 +3,6 @@
namespace App\Http\Controllers\Frontend;
use App\Contracts\Controller;
use App\Models\Airline;
use App\Models\File;
use Auth;
use Flash;
@@ -19,7 +18,6 @@ class DownloadController extends Controller
*/
public function index()
{
$airlines = Airline::where('active', 1)->count();
$files = File::orderBy('ref_model', 'asc')->get();
/**
@@ -41,28 +39,19 @@ class DownloadController extends Controller
$klass = new $class();
$obj = $klass->find($id);
// Check if the object is there first
if (isset($obj)) {
$category = explode('\\', $class);
$category = end($category);
$category = explode('\\', $class);
$category = end($category);
if ($category == 'Aircraft' && $airlines > 1) {
$group_name = $category.' > '.$obj->subfleet->airline->name.' '.$obj->icao.' '.$obj->registration;
} elseif ($category == 'Aircraft') {
$group_name = $category.' > '.$obj->icao.' '.$obj->registration;
} elseif ($category == 'Airport') {
$group_name = $category.' > '.$obj->icao.' : '.$obj->name.' ('.$obj->country.')';
} elseif ($category == 'Subfleet' && $airlines > 1) {
$group_name = $category.' > '.$obj->airline->name.' '.$obj->name;
} else {
$group_name = $category.' > '.$obj->name;
}
$regrouped_files[$group_name] = $files;
if ($category == 'Aircraft') {
$group_name = $category.' > '.$obj->icao.' '.$obj->registration;
} elseif ($category == 'Airport') {
$group_name = $category.' > '.$obj->icao.' : '.$obj->name.' ('.$obj->country.')';
} else {
$group_name = $category.' > '.$obj->name;
}
}
ksort($regrouped_files, SORT_STRING);
$regrouped_files[$group_name] = $files;
}
return view('downloads.index', [
'grouped_files' => $regrouped_files,
@@ -70,7 +59,7 @@ class DownloadController extends Controller
}
/**
* Show the application dashboard
* Show the application dashboard.
*
* @param string $id
*

View File

@@ -5,7 +5,6 @@ namespace App\Http\Controllers\Frontend;
use App\Contracts\Controller;
use App\Models\Bid;
use App\Models\Enums\FlightType;
use App\Models\Flight;
use App\Repositories\AirlineRepository;
use App\Repositories\AirportRepository;
use App\Repositories\Criteria\WhereCriteria;
@@ -13,7 +12,6 @@ use App\Repositories\FlightRepository;
use App\Repositories\SubfleetRepository;
use App\Repositories\UserRepository;
use App\Services\GeoService;
use App\Services\ModuleService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
@@ -26,7 +24,6 @@ class FlightController extends Controller
private $airlineRepo;
private $airportRepo;
private $flightRepo;
private $moduleSvc;
private $subfleetRepo;
private $geoSvc;
private $userRepo;
@@ -36,7 +33,6 @@ class FlightController extends Controller
* @param AirportRepository $airportRepo
* @param FlightRepository $flightRepo
* @param GeoService $geoSvc
* @param ModuleService $moduleSvc
* @param SubfleetRepository $subfleetRepo
* @param UserRepository $userRepo
*/
@@ -45,7 +41,6 @@ class FlightController extends Controller
AirportRepository $airportRepo,
FlightRepository $flightRepo,
GeoService $geoSvc,
ModuleService $moduleSvc,
SubfleetRepository $subfleetRepo,
UserRepository $userRepo
) {
@@ -53,7 +48,6 @@ class FlightController extends Controller
$this->airportRepo = $airportRepo;
$this->flightRepo = $flightRepo;
$this->geoSvc = $geoSvc;
$this->moduleSvc = $moduleSvc;
$this->subfleetRepo = $subfleetRepo;
$this->userRepo = $userRepo;
}
@@ -111,20 +105,6 @@ class FlightController extends Controller
Log::emergency($e);
}
// Get only used Flight Types for the search form
// And filter according to settings
$usedtypes = Flight::select('flight_type')
->where($where)
->groupby('flight_type')
->orderby('flight_type')
->get();
// Build collection with type codes and labels
$flight_types = collect('', '');
foreach ($usedtypes as $ftype) {
$flight_types->put($ftype->flight_type, FlightType::label($ftype->flight_type));
}
$flights = $this->flightRepo->searchCriteria($request)
->with([
'dpt_airport',
@@ -133,20 +113,12 @@ class FlightController extends Controller
'simbrief' => function ($query) use ($user) {
$query->where('user_id', $user->id);
}, ])
->orderBy('flight_number')
->orderBy('route_leg')
->orderBy('flight_number', 'asc')
->orderBy('route_leg', 'asc')
->paginate();
$saved_flights = [];
$bids = Bid::where('user_id', Auth::id())->get();
foreach ($bids as $bid) {
if (!$bid->flight) {
$bid->delete();
continue;
}
$saved_flights[$bid->flight_id] = $bid->id;
}
$saved_flights = Bid::where('user_id', Auth::id())
->pluck('flight_id')->toArray();
return view('flights.index', [
'user' => $user,
@@ -156,14 +128,13 @@ class FlightController extends Controller
'saved' => $saved_flights,
'subfleets' => $this->subfleetRepo->selectBoxList(true),
'flight_number' => $request->input('flight_number'),
'flight_types' => $flight_types,
'flight_types' => FlightType::select(true),
'flight_type' => $request->input('flight_type'),
'arr_icao' => $request->input('arr_icao'),
'dep_icao' => $request->input('dep_icao'),
'subfleet_id' => $request->input('subfleet_id'),
'simbrief' => !empty(setting('simbrief.api_key')),
'simbrief_bids' => setting('simbrief.only_bids'),
'acars_plugin' => $this->moduleSvc->isModuleActive('VMSAcars'),
]);
}
@@ -190,7 +161,7 @@ class FlightController extends Controller
}
$flights->add($bid->flight);
$saved_flights[$bid->flight_id] = $bid->id;
$saved_flights[] = $bid->flight->id;
}
return view('flights.bids', [
@@ -202,7 +173,6 @@ class FlightController extends Controller
'subfleets' => $this->subfleetRepo->selectBoxList(true),
'simbrief' => !empty(setting('simbrief.api_key')),
'simbrief_bids' => setting('simbrief.only_bids'),
'acars_plugin' => $this->moduleSvc->isModuleActive('VMSAcars'),
]);
}
@@ -223,14 +193,9 @@ class FlightController extends Controller
$map_features = $this->geoSvc->flightGeoJson($flight);
// See if the user has a bid for this flight
$bid = Bid::where(['user_id' => Auth::id(), 'flight_id' => $flight->id])->first();
return view('flights.show', [
'flight' => $flight,
'map_features' => $map_features,
'bid' => $bid,
'acars_plugin' => $this->moduleSvc->isModuleActive('VMSAcars'),
]);
}
}

View File

@@ -3,7 +3,6 @@
namespace App\Http\Controllers\Frontend;
use App\Contracts\Controller;
use App\Models\Enums\UserState;
use App\Models\User;
use Illuminate\Database\QueryException;
use Illuminate\Support\Facades\Log;
@@ -16,7 +15,7 @@ class HomeController extends Controller
public function index()
{
try {
$users = User::where('state', '!=', UserState::DELETED)->orderBy('created_at', 'desc')->take(4)->get();
$users = User::orderBy('created_at', 'desc')->take(4)->get();
} catch (\PDOException $e) {
Log::emergency($e);
return view('system/errors/database_error', [

View File

@@ -9,7 +9,6 @@ use App\Models\Enums\PirepSource;
use App\Models\Enums\PirepState;
use App\Models\Fare;
use App\Models\Pirep;
use App\Models\PirepFare;
use App\Models\SimBrief;
use App\Models\User;
use App\Repositories\AircraftRepository;
@@ -104,7 +103,7 @@ class PirepController extends Controller
$tmp[$ac->id] = $ac['name'].' - '.$ac['registration'];
}
$aircraft[$subfleet->type] = $tmp;
$aircraft[$subfleet->name] = $tmp;
}
return $aircraft;
@@ -113,18 +112,19 @@ class PirepController extends Controller
/**
* Save any custom fields found
*
* @param Pirep $pirep
* @param Request $request
*/
protected function saveCustomFields(Request $request): array
protected function saveCustomFields(Pirep $pirep, Request $request)
{
$fields = [];
$custom_fields = [];
$pirep_fields = $this->pirepFieldRepo->all();
foreach ($pirep_fields as $field) {
if (!$request->filled($field->slug)) {
continue;
}
$fields[] = [
$custom_fields[] = [
'name' => $field->name,
'slug' => $field->slug,
'value' => $request->input($field->slug),
@@ -132,9 +132,8 @@ class PirepController extends Controller
];
}
Log::info('PIREP Custom Fields', $fields);
return $fields;
Log::info('PIREP Custom Fields', $custom_fields);
$this->pirepSvc->updateCustomFields($pirep->id, $custom_fields);
}
/**
@@ -160,10 +159,10 @@ class PirepController extends Controller
$count = $request->input($field_name);
}
$fares[] = new PirepFare([
$fares[] = [
'fare_id' => $fare->id,
'count' => $count,
]);
];
}
$this->fareSvc->saveForPirep($pirep, $fares);
@@ -212,7 +211,6 @@ class PirepController extends Controller
return view('pireps.show', [
'pirep' => $pirep,
'map_features' => $map_features,
'user' => Auth::user(),
]);
}
@@ -390,8 +388,8 @@ class PirepController extends Controller
$attrs['submitted_at'] = Carbon::now('UTC');
$pirep->submitted_at = Carbon::now('UTC');
$fields = $this->saveCustomFields($request);
$pirep = $this->pirepSvc->create($pirep, $fields);
$pirep = $this->pirepSvc->create($pirep);
$this->saveCustomFields($pirep, $request);
$this->saveFares($pirep, $request);
$this->pirepSvc->saveRoute($pirep);
@@ -400,13 +398,7 @@ class PirepController extends Controller
if ($brief !== null) {
/** @var SimBriefService $sbSvc */
$sbSvc = app(SimBriefService::class);
// Keep the flight_id with SimBrief depending on the button selected
// Save = Keep the flight_id , Submit = Remove the flight_id
if ($attrs['submit'] === 'save') {
$sbSvc->attachSimbriefToPirep($pirep, $brief, true);
} elseif ($attrs['submit'] === 'submit') {
$sbSvc->attachSimbriefToPirep($pirep, $brief);
}
$sbSvc->attachSimbriefToPirep($pirep, $brief);
}
}
@@ -436,18 +428,12 @@ class PirepController extends Controller
*/
public function edit($id)
{
/** @var Pirep $pirep */
$pirep = $this->pirepRepo->findWithoutFail($id);
if (empty($pirep)) {
Flash::error('Pirep not found');
return redirect(route('frontend.pireps.index'));
}
if ($pirep->user_id !== Auth::id()) {
Flash::error('Cannot edit someone else\'s PIREP!');
return redirect(route('admin.pireps.index'));
}
// Eager load the subfleet and fares under it
if ($pirep->aircraft) {
$pirep->aircraft->load('subfleet.fares');
@@ -500,21 +486,12 @@ class PirepController extends Controller
*/
public function update($id, UpdatePirepRequest $request)
{
/** @var User $user */
$user = Auth::user();
/** @var Pirep $pirep */
$pirep = $this->pirepRepo->findWithoutFail($id);
if (empty($pirep)) {
Flash::error('Pirep not found');
return redirect(route('admin.pireps.index'));
}
if ($user->id !== $pirep->user_id) {
Flash::error('Cannot edit someone else\'s PIREP!');
return redirect(route('admin.pireps.index'));
}
$orig_route = $pirep->route;
$attrs = $request->all();
$attrs['submit'] = strtolower($attrs['submit']);
@@ -532,8 +509,7 @@ class PirepController extends Controller
$this->pirepSvc->saveRoute($pirep);
}
$fields = $this->saveCustomFields($request);
$this->pirepSvc->updateCustomFields($pirep->id, $fields);
$this->saveCustomFields($pirep, $request);
$this->saveFares($pirep, $request);
if ($attrs['submit'] === 'save') {
@@ -568,11 +544,6 @@ class PirepController extends Controller
return redirect(route('admin.pireps.index'));
}
if ($pirep->user_id !== Auth::id()) {
Flash::error('Cannot edit someone else\'s PIREP!');
return redirect(route('admin.pireps.index'));
}
$this->pirepSvc->submit($pirep);
return redirect(route('frontend.pireps.show', [$pirep->id]));
}

View File

@@ -10,7 +10,6 @@ use App\Repositories\AirlineRepository;
use App\Repositories\AirportRepository;
use App\Repositories\UserRepository;
use App\Support\Countries;
use App\Support\Discord;
use App\Support\Timezonelist;
use App\Support\Utils;
use Illuminate\Http\Request;
@@ -123,7 +122,7 @@ class ProfileController extends Controller
$airlines = $this->airlineRepo->selectBoxList();
$airports = $this->airportRepo->selectBoxList(false, setting('pilots.home_hubs_only'));
$userFields = $this->userRepo->getUserFields($user);
$userFields = $this->userRepo->getUserFields($user, true);
return view('profile.edit', [
'user' => $user,
@@ -182,16 +181,6 @@ class ProfileController extends Controller
Storage::delete($user->avatar);
}
// Find out the user's private channel id
/*
// TODO: Uncomment when Discord API functionality is enabled
if ($request->filled('discord_id')) {
$discord_id = $request->post('discord_id');
if ($discord_id !== $user->discord_id) {
$req_data['discord_private_channel_id'] = Discord::getPrivateChannelId($discord_id);
}
}*/
if ($request->hasFile('avatar')) {
$avatar = $request->file('avatar');
$file_name = $user->ident.'.'.$avatar->getClientOriginalExtension();

View File

@@ -4,9 +4,6 @@ namespace App\Http\Controllers\Frontend;
use App\Exceptions\AssetNotFound;
use App\Models\Aircraft;
use App\Models\Bid;
use App\Models\Enums\AircraftState;
use App\Models\Enums\AircraftStatus;
use App\Models\Enums\FareType;
use App\Models\Enums\FlightType;
use App\Models\Fare;
@@ -15,7 +12,6 @@ use App\Models\SimBrief;
use App\Models\User;
use App\Repositories\FlightRepository;
use App\Services\FareService;
use App\Services\ModuleService;
use App\Services\SimBriefService;
use App\Services\UserService;
use Exception;
@@ -26,20 +22,17 @@ class SimBriefController
{
private $fareSvc;
private $flightRepo;
private $moduleSvc;
private $simBriefSvc;
private $userSvc;
public function __construct(
FareService $fareSvc,
FlightRepository $flightRepo,
ModuleService $moduleSvc,
SimBriefService $simBriefSvc,
UserService $userSvc
) {
$this->fareSvc = $fareSvc;
$this->flightRepo = $flightRepo;
$this->moduleSvc = $moduleSvc;
$this->simBriefSvc = $simBriefSvc;
$this->userSvc = $userSvc;
}
@@ -75,9 +68,6 @@ class SimBriefController
return redirect(route('frontend.flights.index'));
}
// Generate SimBrief Static ID
$static_id = $user->ident.'_'.$flight->id;
// No aircraft selected, show selection form
if (!$aircraft_id) {
// If no subfleets defined for flight get them from user
@@ -87,38 +77,8 @@ class SimBriefController
$subfleets = $this->userSvc->getAllowableSubfleets($user);
}
// Build an array of subfleet id's from the subfleets collection
$sf_ids = $subfleets->map(function ($subfleets) {
return collect($subfleets->toArray())
->only(['id'])
->all();
});
// Now we can build a proper aircrafts collection
// Contents will be either members of flight->subfleets
// or members of user's allowable subfleets
$aircrafts = Aircraft::whereIn('subfleet_id', $sf_ids)
->where('state', AircraftState::PARKED)
->where('status', AircraftStatus::ACTIVE)
->orderby('icao')
->orderby('registration')
->get();
if (setting('pireps.only_aircraft_at_dpt_airport')) {
$aircrafts = $aircrafts->where('airport_id', $flight->dpt_airport_id);
}
if (setting('simbrief.block_aircraft')) {
// Build a list of aircraft_id's being used for active sb packs
$sb_aircraft = SimBrief::whereNotNull('flight_id')->pluck('aircraft_id');
// Filter aircraft list to non used/blocked ones
$aircrafts = $aircrafts->whereNotIn('id', $sb_aircraft);
}
return view('flights.simbrief_aircraft', [
'flight' => $flight,
'aircrafts' => $aircrafts,
'subfleets' => $subfleets,
]);
}
@@ -231,7 +191,7 @@ class SimBriefController
// Show the main simbrief form
return view('flights.simbrief_form', [
'user' => $user,
'user' => Auth::user(),
'flight' => $flight,
'aircraft' => $aircraft,
'pax_weight' => $pax_weight,
@@ -246,7 +206,6 @@ class SimBriefController
'tpayload' => $tpayload,
'tcargoload' => $tcargoload,
'loaddist' => implode(' ', $loaddist),
'static_id' => $static_id,
]);
}
@@ -259,11 +218,7 @@ class SimBriefController
*/
public function briefing($id)
{
/** @var User $user */
$user = Auth::user();
/** @var SimBrief $simbrief */
$simbrief = SimBrief::with(['flight'])->find($id);
$simbrief = SimBrief::find($id);
if (!$simbrief) {
flash()->error('SimBrief briefing not found');
return redirect(route('frontend.flights.index'));
@@ -276,18 +231,11 @@ class SimBriefController
$equipment = substr($str, $wc + 1, $tr - 2);
$transponder = substr($str, $tr + 1);
// See if a bid exists for this flight
$bid = Bid::where(['user_id' => $user->id, 'flight_id' => $simbrief->flight_id])->first();
return view('flights.simbrief_briefing', [
'user' => $user,
'simbrief' => $simbrief,
'wakecat' => $wakecat,
'equipment' => $equipment,
'transponder' => $transponder,
'bid' => $bid,
'flight' => $simbrief->flight,
'acars_plugin' => $this->moduleSvc->isModuleActive('VMSAcars'),
'simbrief' => $simbrief,
'wakecat' => $wakecat,
'equipment' => $equipment,
'transponder' => $transponder,
]);
}
@@ -388,31 +336,6 @@ class SimBriefController
]);
}
/**
* Get the latest generated OFP. Pass in two additional items, the Simbrief userid and static_id
* This will get the latest edited/regenerated of from Simbrief and update our records
* We do not need to send the fares again, so used an empty array
*/
public function update_ofp(Request $request)
{
/** @var User $user */
$user = Auth::user();
$ofp_id = $request->input('ofp_id');
$flight_id = $request->input('flight_id');
$aircraft_id = $request->input('aircraft_id');
$sb_userid = $request->input('sb_userid');
$sb_static_id = $request->input('sb_static_id');
$fares = [];
$simbrief = $this->simBriefSvc->downloadOfp($user->id, $ofp_id, $flight_id, $aircraft_id, $fares, $sb_userid, $sb_static_id);
if ($simbrief === null) {
$error = new AssetNotFound(new Exception('Simbrief OFP not found'));
return $error->getResponse();
}
return redirect(route('frontend.simbrief.briefing', [$ofp_id]));
}
/**
* Generate the API code
*

View File

@@ -25,6 +25,7 @@ use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Validator;
use Illuminate\View\View;
use function in_array;
use Laracasts\Flash\Flash;
use RuntimeException;
class InstallerController extends Controller
@@ -202,21 +203,21 @@ class InstallerController extends Controller
Log::error('Testing db before writing configs failed');
Log::error($e->getMessage());
flash()->error($e->getMessage());
Flash::error($e->getMessage());
return redirect(route('installer.step2'))->withInput();
}
// Now write out the env file
$attrs = [
'SITE_NAME' => $request->post('site_name'),
'APP_URL' => $request->post('app_url'),
'DB_CONNECTION' => $request->post('db_conn'),
'DB_HOST' => $request->post('db_host'),
'DB_PORT' => $request->post('db_port'),
'DB_DATABASE' => $request->post('db_name'),
'DB_USERNAME' => $request->post('db_user'),
'DB_PASSWORD' => $request->post('db_pass'),
'DB_PREFIX' => $request->post('db_prefix'),
'SITE_NAME' => $request->post('site_name'),
'SITE_URL' => $request->post('site_url'),
'DB_CONN' => $request->post('db_conn'),
'DB_HOST' => $request->post('db_host'),
'DB_PORT' => $request->post('db_port'),
'DB_NAME' => $request->post('db_name'),
'DB_USER' => $request->post('db_user'),
'DB_PASS' => $request->post('db_pass'),
'DB_PREFIX' => $request->post('db_prefix'),
];
/*
@@ -230,7 +231,7 @@ class InstallerController extends Controller
Log::error('Config files failed to write');
Log::error($e->getMessage());
flash()->error($e->getMessage());
Flash::error($e->getMessage());
return redirect(route('installer.step2'))->withInput();
}
@@ -256,7 +257,7 @@ class InstallerController extends Controller
Log::error('Error on db setup: '.$e->getMessage());
//dd($e);
$this->envSvc->removeConfigFiles();
flash()->error($e->getMessage());
Flash::error($e->getMessage());
return redirect(route('installer.step2'))->withInput();
}

View File

@@ -3,32 +3,49 @@
namespace App\Http\Controllers\System;
use App\Contracts\Controller;
use App\Repositories\KvpRepository;
use App\Services\AnalyticsService;
use App\Services\Installer\InstallerService;
use App\Services\Installer\MigrationService;
use App\Services\Installer\SeederService;
use Codedge\Updater\UpdaterManager;
use function count;
use Illuminate\Contracts\View\Factory;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\View\View;
class UpdateController extends Controller
{
private $analyticsSvc;
private $installerSvc;
private $kvpRepo;
private $migrationSvc;
private $seederSvc;
private $updateManager;
/**
* @param AnalyticsService $analyticsSvc
* @param InstallerService $installerSvc
* @param KvpRepository $kvpRepo
* @param MigrationService $migrationSvc
* @param SeederService $seederSvc
* @param UpdaterManager $updateManager
*/
public function __construct(
AnalyticsService $analyticsSvc,
InstallerService $installerSvc,
KvpRepository $kvpRepo,
MigrationService $migrationSvc,
SeederService $seederSvc
SeederService $seederSvc,
UpdaterManager $updateManager
) {
$this->analyticsSvc = $analyticsSvc;
$this->migrationSvc = $migrationSvc;
$this->seederSvc = $seederSvc;
$this->installerSvc = $installerSvc;
$this->kvpRepo = $kvpRepo;
$this->updateManager = $updateManager;
}
/**
@@ -90,4 +107,38 @@ class UpdateController extends Controller
{
return redirect('/admin');
}
/**
* Show the update page with the latest version
*
* @return Factory|View
*/
public function updater()
{
$version = $this->kvpRepo->get('latest_version_tag');
return view('system.updater.downloader/downloader', [
'version' => $version,
]);
}
/**
* Download the actual update and then forward the user to the updater page
*
* @return mixed
*/
public function update_download()
{
$version = $this->kvpRepo->get('latest_version_tag');
if (empty($version)) {
return view('system.updater.steps.step1-no-update');
}
$release = $this->updateManager->source('github')->fetch($version);
$this->updateManager->source('github')->update($release);
$this->analyticsSvc->sendUpdate();
Log::info('Update completed to '.$version.', redirecting');
return redirect('/update');
}
}

View File

@@ -50,9 +50,6 @@ class ApiAuth implements Middleware
return $user;
});
// Force english locale for API
app()->setLocale('en');
return $next($request);
}

View File

@@ -15,7 +15,6 @@ class JsonResponse implements Middleware
{
$response = $next($request);
$response->headers->set('Content-Type', 'application/json');
$response->headers->set('charset', 'utf-8');
return $response;
}

View File

@@ -52,7 +52,7 @@ class SetActiveTheme implements Middleware
}
try {
$theme = setting('general.theme', 'default');
$theme = setting('general.theme');
} catch (\Exception $e) {
Log::error($e->getMessage());
$theme = 'default';

View File

@@ -19,7 +19,7 @@ class FileRequest extends FormRequest
return [
'distance' => 'required|numeric',
'flight_time' => 'required|integer',
'fuel_used' => 'sometimes|numeric',
'fuel_used' => 'required|numeric',
'block_time' => 'sometimes|integer',
'airline_id' => 'sometimes|exists:airlines,id',
'aircraft_id' => 'sometimes|exists:aircraft,id',

View File

@@ -9,7 +9,7 @@ class Bid extends Resource
public function toArray($request)
{
$res = parent::toArray($request);
$res['flight'] = new BidFlight($this->flight);
$res['flight'] = new Flight($this->flight);
return $res;
}

View File

@@ -1,36 +0,0 @@
<?php
namespace App\Http\Resources;
use App\Http\Resources\SimBrief as SimbriefResource;
/**
* @mixin \App\Models\Flight
*/
class BidFlight extends Flight
{
/**
* @param \Illuminate\Http\Request $request
*
* @throws \PhpUnitsOfMeasure\Exception\NonNumericValue
* @throws \PhpUnitsOfMeasure\Exception\NonStringUnitName
*
* @return array
*/
public function toArray($request)
{
$res = parent::toArray($request);
if ($this->whenLoaded('simbrief')) {
unset($res['subfleets']);
$res['simbrief'] = new SimbriefResource($this->simbrief);
} else {
unset($res['simbrief']);
$res['subfleets'] = Subfleet::collection($this->whenLoaded('subfleets'));
}
$res['fields'] = $this->setFields();
return $res;
}
}

View File

@@ -1,41 +0,0 @@
<?php
namespace App\Http\Resources;
class BidSubfleet extends Subfleet
{
protected $aircraft;
protected $fares;
public function __construct($resource, $aircraft, $fares)
{
parent::__construct($resource);
$this->aircraft = $aircraft;
$this->fares = $fares;
}
public function toArray($request)
{
$res = [];
$res['airline_id'] = $this->airline_id;
$res['hub_id'] = $this->hub_id;
$res['type'] = $this->type;
$res['simbrief_type'] = $this->simbrief_type;
$res['name'] = $this->name;
$res['fuel_type'] = $this->fuel_type;
$res['cost_block_hour'] = $this->cost_block_hour;
$res['cost_delay_minute'] = $this->cost_delay_minute;
$res['ground_handling_multiplier'] = $this->ground_handling_multiplier;
$res['cargo_capacity'] = $this->cargo_capacity;
$res['fuel_capacity'] = $this->fuel_capacity;
$res['gross_weight'] = $this->gross_weight;
$res['fares'] = Fare::collection($this->fares);
// There should only be one aircraft tied to a bid subfleet, wrap in a collection
$res['aircraft'] = Aircraft::collection([$this->aircraft]);
return $res;
}
}

View File

@@ -15,7 +15,7 @@ class Flight extends Resource
/**
* Set the fields on the flight object
*/
protected function setFields()
private function setFields()
{
/** @var \Illuminate\Support\Collection $field_values */
$return_values = new stdClass();

View File

@@ -18,7 +18,7 @@ class News extends Resource
$res = parent::toArray($request);
$res['user'] = [
'id' => $this->user->id,
'name' => $this->user->name_private,
'name' => $this->user->name,
];
return $res;

View File

@@ -12,27 +12,25 @@ class SimBrief extends Resource
public function toArray($request)
{
$data = [
'id' => $this->id,
'aircraft_id' => $this->aircraft_id,
'url' => url(route('api.flights.briefing', ['id' => $this->id])),
'id' => $this->id,
'url' => url(route('api.flights.briefing', ['id' => $this->id])),
];
$fares = [];
try {
if (!empty($this->fare_data)) {
$fares = [];
$fare_data = json_decode($this->fare_data, true);
foreach ($fare_data as $fare) {
$fares[] = new \App\Models\Fare($fare);
}
$fares = collect($fares);
$this->aircraft->subfleet->fares = collect($fares);
}
} catch (\Exception $e) {
// Invalid fare data
}
$data['subfleet'] = new BidSubfleet($this->aircraft->subfleet, $this->aircraft, $fares);
$data['subfleet'] = new Subfleet($this->aircraft->subfleet);
return $data;
}

View File

@@ -3,7 +3,8 @@
namespace App\Listeners;
use App\Contracts\Listener;
use App\Events\PirepFiled;
use App\Events\PirepAccepted;
use App\Events\PirepRejected;
use App\Services\BidService;
/**
@@ -12,7 +13,8 @@ use App\Services\BidService;
class BidEventHandler extends Listener
{
public static $callbacks = [
PirepFiled::class => 'onPirepFiled',
PirepAccepted::class => 'onPirepAccept',
PirepRejected::class => 'onPirepReject',
];
private $bidSvc;
@@ -23,15 +25,29 @@ class BidEventHandler extends Listener
}
/**
* When a PIREP is filed, remove any bids
* When a PIREP is accepted, remove any bids
*
* @param PirepFiled $event
* @param PirepAccepted $event
*
* @throws \UnexpectedValueException
* @throws \InvalidArgumentException
* @throws \Exception
*/
public function onPirepFiled(PirepFiled $event): void
public function onPirepAccept(PirepAccepted $event): void
{
$this->bidSvc->removeBidForPirep($event->pirep);
}
/**
* When a PIREP is accepted, remove any bids
*
* @param PirepRejected $event
*
* @throws \UnexpectedValueException
* @throws \InvalidArgumentException
* @throws \Exception
*/
public function onPirepReject(PirepRejected $event): void
{
$this->bidSvc->removeBidForPirep($event->pirep);
}

View File

@@ -1,22 +0,0 @@
<?php
namespace App\Listeners;
use Illuminate\Log\Events\MessageLogged;
use Symfony\Component\Console\Output\ConsoleOutput;
/**
* Show logs in the console
*
* https://stackoverflow.com/questions/48264479/log-laravel-with-artisan-output
*/
class MessageLoggedListener
{
public function handle(MessageLogged $event)
{
if (app()->runningInConsole() && app()->environment() !== 'testing') {
$output = new ConsoleOutput();
$output->writeln("<$event->level>$event->message</$event->level>");
}
}
}

View File

@@ -1,26 +0,0 @@
<?php
namespace App\Listeners;
use App\Contracts\Listener;
use App\Events\PirepPrefiled;
/**
* Handler for PIREP events
*/
class PirepEventsHandler extends Listener
{
/** The events and the callback */
public static $callbacks = [
PirepPrefiled::class => 'onPirepPrefile',
];
/**
* Called when a PIREP is prefiled
*
* @param PirepPrefiled $event
*/
public function onPirepPrefile(PirepPrefiled $event)
{
}
}

View File

@@ -12,7 +12,6 @@ use Carbon\Carbon;
* @property int id
* @property mixed subfleet_id
* @property string airport_id The apt where the aircraft is
* @property string ident
* @property string name
* @property string icao
* @property string registration
@@ -25,7 +24,6 @@ use Carbon\Carbon;
* @property int status
* @property int state
* @property Carbon landing_time
* @property float fuel_onboard
*/
class Aircraft extends Model
{
@@ -72,14 +70,6 @@ class Aircraft extends Model
'zfw' => 'nullable|numeric',
];
/**
* @return string
*/
public function getIdentAttribute(): string
{
return $this->registration.' ('.$this->icao.')';
}
/**
* See if this aircraft is active
*

View File

@@ -6,7 +6,6 @@ use App\Contracts\Model;
use App\Models\Enums\JournalType;
use App\Models\Traits\FilesTrait;
use App\Models\Traits\JournalTrait;
use Illuminate\Support\Str;
/**
* Class Airline
@@ -85,7 +84,7 @@ class Airline extends Model
*/
public function setIataAttribute($iata)
{
$this->attributes['iata'] = Str::upper($iata);
$this->attributes['iata'] = strtoupper($iata);
}
/**
@@ -95,7 +94,7 @@ class Airline extends Model
*/
public function setIcaoAttribute($icao): void
{
$this->attributes['icao'] = Str::upper($icao);
$this->attributes['icao'] = strtoupper($icao);
}
public function subfleets()

View File

@@ -46,7 +46,6 @@ class Airport extends Model
'lon',
'hub',
'timezone',
'tz',
'ground_handling_cost',
'fuel_100ll_cost',
'fuel_jeta_cost',

View File

@@ -6,7 +6,7 @@ use App\Contracts\Model;
use Carbon\Carbon;
/**
* @property int user_id
* @property string user_id
* @property string flight_id
* @property Carbon created_at
* @property Carbon updated_at

View File

@@ -77,7 +77,7 @@ class Days extends Enum
*/
public static function in($mask, $day): bool
{
return in_mask($mask, $day);
return ($mask & $day) === $day;
}
/**

View File

@@ -4,6 +4,9 @@ namespace App\Models\Enums;
use App\Contracts\Enum;
/**
* Class PirepState
*/
class PirepState extends Enum
{
public const IN_PROGRESS = 0; // flight is ongoing
@@ -13,7 +16,6 @@ class PirepState extends Enum
public const DELETED = 4;
public const DRAFT = 5;
public const REJECTED = 6;
public const PAUSED = 7;
protected static $labels = [
self::IN_PROGRESS => 'pireps.state.in_progress',
@@ -23,6 +25,5 @@ class PirepState extends Enum
self::DELETED => 'pireps.state.deleted',
self::DRAFT => 'pireps.state.draft',
self::REJECTED => 'pireps.state.rejected',
self::PAUSED => 'pireps.state.paused',
];
}

View File

@@ -33,8 +33,7 @@ class PirepStatus extends Enum
public const LANDED = 'LAN';
public const ARRIVED = 'ONB'; // On block
public const CANCELLED = 'DX';
public const EMERG_DESCENT = 'EMG';
public const PAUSED = 'PSD';
public const EMERG_DECENT = 'EMG';
protected static $labels = [
self::INITIATED => 'pireps.status.initialized',
@@ -59,7 +58,6 @@ class PirepStatus extends Enum
self::LANDED => 'pireps.status.landed',
self::ARRIVED => 'pireps.status.arrived',
self::CANCELLED => 'pireps.status.cancelled',
self::EMERG_DESCENT => 'pireps.status.emerg_decent',
self::PAUSED => 'pireps.status.paused',
self::EMERG_DECENT => 'pireps.status.emerg_decent',
];
}

View File

@@ -11,7 +11,6 @@ class UserState extends Enum
public const REJECTED = 2;
public const ON_LEAVE = 3;
public const SUSPENDED = 4;
public const DELETED = 5;
protected static $labels = [
self::PENDING => 'user.state.pending',
@@ -19,6 +18,5 @@ class UserState extends Enum
self::REJECTED => 'user.state.rejected',
self::ON_LEAVE => 'user.state.on_leave',
self::SUSPENDED => 'user.state.suspended',
self::DELETED => 'user.state.deleted',
];
}

View File

@@ -13,7 +13,6 @@ use App\Models\Traits\ReferenceTrait;
* @property string flight_type
* @property string ref_model
* @property string ref_model_id
* @property bool charge_to_user
*
* @mixin \Illuminate\Database\Eloquent\Builder
*/
@@ -37,7 +36,7 @@ class Expense extends Model
];
public static $rules = [
'active' => 'bool',
'active' => 'boolean',
'airline_id' => 'integer',
'amount' => 'float',
'multiplier' => 'bool',

View File

@@ -15,7 +15,6 @@ use Illuminate\Support\Collection;
* @property Airline airline
* @property int airline_id
* @property mixed flight_number
* @property mixed callsign
* @property mixed route_code
* @property int route_leg
* @property bool has_bid
@@ -61,7 +60,6 @@ class Flight extends Model
'id',
'airline_id',
'flight_number',
'callsign',
'route_code',
'route_leg',
'dpt_airport_id',
@@ -106,7 +104,6 @@ class Flight extends Model
public static $rules = [
'airline_id' => 'required|exists:airlines,id',
'flight_number' => 'required',
'callsign' => 'string|max:4|nullable',
'route_code' => 'nullable',
'route_leg' => 'nullable',
'dpt_airport_id' => 'required|exists:airports,id',

View File

@@ -186,7 +186,7 @@ class Journal extends Model
*/
public function getCurrentBalance()
{
return $this->getBalanceOn(Carbon::now('UTC'));
return $this->getBalanceOn(Carbon::now());
}
/**

View File

@@ -3,19 +3,13 @@
namespace App\Models;
use App\Contracts\Model;
use Illuminate\Notifications\Notifiable;
/**
* @property int id
* @property int|mixed user_id
* @property string subject
* @property string body
* @property User user
* @property string subject
* @property string body
*/
class News extends Model
{
use Notifiable;
public $table = 'news';
protected $fillable = [

View File

@@ -3,8 +3,6 @@
namespace App\Models;
use App\Contracts\Model;
use App\Events\PirepStateChange;
use App\Events\PirepStatusChange;
use App\Models\Enums\AcarsType;
use App\Models\Enums\PirepFieldSource;
use App\Models\Enums\PirepState;
@@ -12,9 +10,7 @@ use App\Models\Traits\HashIdTrait;
use App\Support\Units\Distance;
use App\Support\Units\Fuel;
use Carbon\Carbon;
use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Collection;
use Kleemans\AttributeEvents;
/**
* @property string id
@@ -48,9 +44,8 @@ use Kleemans\AttributeEvents;
* @property Flight|null flight
* @property Collection fields
* @property string status
* @property int state
* @property int source
* @property string source_name
* @property bool state
* @property string source
* @property Carbon submitted_at
* @property Carbon created_at
* @property Carbon updated_at
@@ -61,9 +56,7 @@ use Kleemans\AttributeEvents;
*/
class Pirep extends Model
{
use AttributeEvents;
use HashIdTrait;
use Notifiable;
public $table = 'pireps';
@@ -143,14 +136,6 @@ class Pirep extends Model
'route' => 'nullable',
];
/**
* Auto-dispatch events for lifecycle state changes
*/
protected $dispatchesEvents = [
'status:*' => PirepStatusChange::class,
'state:*' => PirepStateChange::class,
];
/*
* If a PIREP is in these states, then it can't be changed.
*/
@@ -195,22 +180,22 @@ class Pirep extends Model
/**
* Create a new PIREP from a SimBrief instance
*
* @param \App\Models\SimBrief $simbrief
* @param \App\Models\SimBrief $simBrief
*
* @return \App\Models\Pirep
*/
public static function fromSimBrief(SimBrief $simbrief): self
public static function fromSimBrief(SimBrief $simBrief): self
{
return new self([
'flight_id' => $simbrief->flight->id,
'airline_id' => $simbrief->flight->airline_id,
'flight_number' => $simbrief->flight->flight_number,
'route_code' => $simbrief->flight->route_code,
'route_leg' => $simbrief->flight->route_leg,
'dpt_airport_id' => $simbrief->flight->dpt_airport_id,
'arr_airport_id' => $simbrief->flight->arr_airport_id,
'route' => $simbrief->xml->getRouteString(),
'level' => $simbrief->xml->getFlightLevel(),
'flight_id' => $simBrief->flight->id,
'airline_id' => $simBrief->flight->airline_id,
'flight_number' => $simBrief->flight->flight_number,
'route_code' => $simBrief->flight->route_code,
'route_leg' => $simBrief->flight->route_leg,
'dpt_airport_id' => $simBrief->flight->dpt_airport_id,
'arr_airport_id' => $simBrief->flight->arr_airport_id,
'route' => $simBrief->xml->getRouteString(),
'level' => $simBrief->xml->getFlightLevel(),
]);
}

View File

@@ -11,7 +11,6 @@ use App\Models\Enums\PirepFieldSource;
* @property string slug
* @property string value
* @property string source
* @property Pirep pirep
*
* @method static updateOrCreate(array $array, array $array1)
*/

View File

@@ -5,12 +5,6 @@ namespace App\Models;
use Laratrust\Models\LaratrustRole;
/**
* @property int id
* @property string name
* @property string display_name
* @property bool read_only
* @property bool disable_activity_checks
*
* @mixin \Illuminate\Database\Eloquent\Builder
*/
class Role extends LaratrustRole
@@ -20,12 +14,10 @@ class Role extends LaratrustRole
'name',
'display_name',
'read_only',
'disable_activity_checks',
];
protected $casts = [
'read_only' => 'boolean',
'disable_activity_checks' => 'boolean',
'read_only' => 'boolean',
];
/**

View File

@@ -41,10 +41,6 @@ class SimBrief extends Model
'updated_at',
];
protected $casts = [
'user_id' => 'integer',
];
/** @var \App\Models\SimBriefXML Store a cached version of the XML object */
private $xml_instance;
@@ -53,7 +49,7 @@ class SimBrief extends Model
*
* @return \App\Models\SimBriefXML|null
*/
public function getXmlAttribute(): ?SimBriefXML
public function getXmlAttribute(): SimBriefXML
{
if (empty($this->attributes['ofp_xml'])) {
return null;
@@ -96,12 +92,13 @@ class SimBrief extends Model
public function flight()
{
return $this->belongsTo(Flight::class, 'flight_id');
}
if (!empty($this->attributes['flight_id'])) {
return $this->belongsTo(Flight::class, 'flight_id');
}
public function pirep()
{
return $this->belongsTo(Pirep::class, 'pirep_id');
if (!empty($this->attributes['pirep_id'])) {
return $this->belongsTo(Pirep::class, 'pirep_id');
}
}
public function user()

View File

@@ -20,7 +20,6 @@ use App\Models\Traits\FilesTrait;
* @property float cost_delay_minute
* @property Airline airline
* @property Airport hub
* @property int fuel_type
*/
class Subfleet extends Model
{

View File

@@ -3,6 +3,7 @@
namespace App\Models;
use App\Models\Enums\JournalType;
use App\Models\Enums\PirepState;
use App\Models\Traits\JournalTrait;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
@@ -32,16 +33,11 @@ use Laratrust\Traits\LaratrustUserTrait;
* @property Rank rank
* @property Journal journal
* @property int rank_id
* @property string discord_id
* @property int state
* @property string last_ip
* @property bool opt_in
* @property Pirep[] pireps
* @property string last_pirep_id
* @property Pirep last_pirep
* @property UserFieldValue[] fields
* @property Role[] roles
* @property Subfleet[] subfleets
*
* @mixin \Illuminate\Database\Eloquent\Builder
* @mixin \Illuminate\Notifications\Notifiable
@@ -68,8 +64,6 @@ class User extends Authenticatable
'pilot_id',
'airline_id',
'rank_id',
'discord_id',
'discord_private_channel_id',
'api_key',
'country',
'home_airport_id',
@@ -84,7 +78,6 @@ class User extends Authenticatable
'status',
'toc_accepted',
'opt_in',
'last_ip',
'created_at',
'updated_at',
];
@@ -94,9 +87,7 @@ class User extends Authenticatable
*/
protected $hidden = [
'api_key',
'discord_id',
'password',
'last_ip',
'remember_token',
];
@@ -258,7 +249,8 @@ class User extends Authenticatable
public function pireps()
{
return $this->hasMany(Pirep::class, 'user_id');
return $this->hasMany(Pirep::class, 'user_id')
->where('state', '!=', PirepState::CANCELLED);
}
public function rank()

View File

@@ -1,145 +0,0 @@
<?php
namespace App\Notifications\Channels\Discord;
use Carbon\Carbon;
/**
* Original is from https://gist.github.com/freekmurze/e4415090f650e070d3de8b905875cf78
*
* Markdown guide: https://birdie0.github.io/discord-webhooks-guide/other/discord_markdown.html
*/
class DiscordMessage
{
const COLOR_SUCCESS = '#0B6623';
const COLOR_WARNING = '#FD6A02';
const COLOR_ERROR = '#ED2939';
public $webhook_url;
protected $title;
protected $url;
protected $description;
protected $timestamp;
protected $footer;
protected $color;
protected $author = [];
protected $fields = [];
/**
* Supply the webhook URL that this should be going to
*/
public function webhook(string $url): self
{
$this->webhook_url = $url;
return $this;
}
/**
* Title of the notification
*/
public function title(string $title): self
{
$this->title = $title;
return $this;
}
public function url(string $url): self
{
$this->url = $url;
return $this;
}
/**
* @param array|string $descriptionLines
*/
public function description($descriptionLines): self
{
if (!is_array($descriptionLines)) {
$descriptionLines = [$descriptionLines];
}
$this->description = implode(PHP_EOL, $descriptionLines);
return $this;
}
/**
* Set the author information:
* [
* 'name' => '',
* 'url' => '',
* 'icon_url' => '',
*/
public function author(array $author): self
{
$this->author = $author;
return $this;
}
/**
* Set the fields
*/
public function fields(array $fields): self
{
$this->fields = [];
foreach ($fields as $name => $value) {
$this->fields[] = [
'name' => '**'.$name.'**', // bold
'value' => $value,
'inline' => true,
];
}
return $this;
}
public function footer(string $footer): self
{
$this->footer = $footer;
return $this;
}
public function success(): self
{
$this->color = static::COLOR_SUCCESS;
return $this;
}
public function warning(): self
{
$this->color = static::COLOR_WARNING;
return $this;
}
public function error(): self
{
$this->color = static::COLOR_ERROR;
return $this;
}
public function toArray(): array
{
$embeds = [
'title' => $this->title,
'url' => $this->url,
'type' => 'rich',
'description' => $this->description,
'author' => $this->author,
'timestamp' => Carbon::now('UTC'),
];
if (!empty($this->fields)) {
$embeds['fields'] = $this->fields;
}
if (!empty($this->footer)) {
$embeds['footer'] = [
'text' => $this->footer,
];
}
return [
'embeds' => [$embeds],
];
}
}

View File

@@ -1,38 +0,0 @@
<?php
namespace App\Notifications\Channels\Discord;
use App\Contracts\Notification;
use App\Support\HttpClient;
use GuzzleHttp\Exception\RequestException;
use GuzzleHttp\Psr7;
use Illuminate\Support\Facades\Log;
class DiscordWebhook
{
private $httpClient;
public function __construct(HttpClient $httpClient)
{
$this->httpClient = $httpClient;
}
public function send($notifiable, Notification $notification)
{
$message = $notification->toDiscordChannel($notifiable);
if ($message === null || empty($message->webhook_url)) {
Log::debug('Discord notifications not configured, skipping');
return;
}
try {
$data = $message->toArray();
$this->httpClient->post($message->webhook_url, $data);
} catch (RequestException $e) {
$request = Psr7\Message::toString($e->getRequest());
$response = Psr7\Message::toString($e->getResponse());
Log::error('Error sending Discord notification: request: '.$e->getMessage().', '.$request);
Log::error('Error sending Discord notification: response: '.$response);
}
}
}

View File

@@ -17,7 +17,7 @@ trait MailChannel
* @param string $template Markdown template to use
* @param array $args Arguments to pass to the template
*/
public function setMailable(string $subject, string $template, array $args)
public function setMailable($subject, $template, $args)
{
$this->mailSubject = $subject;
$this->mailTemplate = $template;

Some files were not shown because too many files have changed in this diff Show More