Compare commits

..
Author SHA1 Message Date
Nabeel Shahzad 18206f4601 Update the meta link to include query strings 2021-06-10 19:29:25 -04:00
271 changed files with 26447 additions and 16607 deletions
+4 -15
View File
@@ -15,10 +15,7 @@ declare -a remove_files=(
.idea .idea
.travis .travis
docker docker
node_modules
vendor/willdurand/geocoder/tests
_ide_helper.php _ide_helper.php
.env
.dockerignore .dockerignore
.dpl .dpl
.editorconfig .editorconfig
@@ -26,7 +23,6 @@ declare -a remove_files=(
.eslintrc .eslintrc
.php_cs .php_cs
.php_cs.cache .php_cs.cache
.php-cs-fixer.php
.phpstorm.meta.php .phpstorm.meta.php
.styleci.yml .styleci.yml
.phpunit.result.cache .phpunit.result.cache
@@ -41,8 +37,9 @@ declare -a remove_files=(
phpvms.iml phpvms.iml
Procfile Procfile
phpstan.neon phpstan.neon
symfony.lock node_modules
composer.phar composer.phar
vendor/willdurand/geocoder/tests
) )
for file in "${remove_files[@]}"; do for file in "${remove_files[@]}"; do
@@ -73,22 +70,14 @@ mkdir -p storage/framework/views
cd /tmp cd /tmp
echo "Current directory contents"
ls -al $BASE_DIR
echo "Parent directory contents"
ls -al $BASE_DIR/../ ls -al $BASE_DIR/../
echo "Calling find" tar -czf $TAR_NAME -C $BASE_DIR .
find $BASE_DIR/../ -type d -maxdepth 2
tar -czf $TAR_NAME -C $BASE_DIR --xform 's:^\./::' . [--show-transformed-names|--show-stored-names]
sha256sum $TAR_NAME >"$TAR_NAME.sha256" sha256sum $TAR_NAME >"$TAR_NAME.sha256"
cd $BASE_DIR; cd $BASE_DIR;
zip -r $ZIP_NAME ./ zip -r $ZIP_NAME *
sha256sum $ZIP_NAME >"$ZIP_NAME.sha256" sha256sum $ZIP_NAME >"$ZIP_NAME.sha256"
mv $ZIP_NAME /tmp mv $ZIP_NAME /tmp
mv "$ZIP_NAME.sha256" /tmp mv "$ZIP_NAME.sha256" /tmp
+5 -4
View File
@@ -2,12 +2,12 @@ name: 'Build'
on: ['push', 'pull_request', 'workflow_dispatch', 'release'] on: ['push', 'pull_request', 'workflow_dispatch', 'release']
jobs: jobs:
build: build:
runs-on: ubuntu-20.04 runs-on: ubuntu-18.04
if: github.repository == 'nabeelio/phpvms' if: github.repository == 'nabeelio/phpvms'
strategy: strategy:
fail-fast: true fail-fast: true
matrix: matrix:
php-versions: ['7.3', '7.4', '8.0', '8.1'] php-versions: ['7.3', '7.4', '8.0']
name: PHP ${{ matrix.php-versions }} name: PHP ${{ matrix.php-versions }}
env: env:
extensions: intl, pcov, mbstring extensions: intl, pcov, mbstring
@@ -78,8 +78,7 @@ jobs:
- name: Run Tests - name: Run Tests
run: | run: |
export PHP_CS_FIXER_IGNORE_ENV=1 vendor/bin/php-cs-fixer fix --config=.php_cs -v --dry-run --diff --using-cache=no
vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.php -v --dry-run --diff --using-cache=no
vendor/bin/phpunit --debug --verbose vendor/bin/phpunit --debug --verbose
# This runs after all of the tests, run have run. Creates a cleaned up version of the # This runs after all of the tests, run have run. Creates a cleaned up version of the
@@ -117,6 +116,7 @@ jobs:
- name: 'Install Release Dependencies' - name: 'Install Release Dependencies'
run: | run: |
rm -rf vendor rm -rf vendor
sudo npm i tar-to-zip -g
composer install --no-dev --prefer-dist --no-interaction --verbose composer install --no-dev --prefer-dist --no-interaction --verbose
sudo chmod +x ./.github/scripts/* sudo chmod +x ./.github/scripts/*
@@ -179,6 +179,7 @@ jobs:
- name: 'Install Release Dependencies' - name: 'Install Release Dependencies'
run: | run: |
rm -rf vendor rm -rf vendor
sudo npm i tar-to-zip -g
composer install --no-dev --prefer-dist --no-interaction --verbose composer install --no-dev --prefer-dist --no-interaction --verbose
sudo chmod +x ./.github/scripts/* sudo chmod +x ./.github/scripts/*
-1
View File
@@ -76,4 +76,3 @@ error_log
/config.php /config.php
/config.bak.php /config.bak.php
/VERSION /VERSION
sync.sh
-69
View File
@@ -1,69 +0,0 @@
<?php
declare(strict_types=1);
/*
* This file is part of PHP CS Fixer.
*
* (c) Fabien Potencier <fabien@symfony.com>
* Dariusz Rumiński <dariusz.ruminski@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
$header = <<<'EOF'
This file is part of PHP CS Fixer.
(c) Fabien Potencier <fabien@symfony.com>
Dariusz Rumiński <dariusz.ruminski@gmail.com>
This source file is subject to the MIT license that is bundled
with this source code in the file LICENSE.
EOF;
$finder = PhpCsFixer\Finder::create()
->ignoreVCSIgnored(true)
->exclude('tests/data')
->exclude('storage')
->exclude('resources')
->in(__DIR__)
->append([
__DIR__.'/dev-tools/doc.php',
// __DIR__.'/php-cs-fixer', disabled, as we want to be able to run bootstrap file even on lower PHP version, to show nice message
__FILE__,
])
;
$config = new PhpCsFixer\Config();
$config
->setRiskyAllowed(true)
->setRules([
'@PSR2' => true,
'strict_param' => true,
'no_php4_constructor' => true,
'no_extra_blank_lines' => true,
'no_superfluous_elseif' => true,
'single_line_comment_style' => false,
'simple_to_complex_string_variable' => true,
'array_syntax' => [
'syntax' => 'short',
],
'binary_operator_spaces' => [
'operators' => [
'=>' => 'align_single_space_minimal'
]
],
/*
'blank_line_before_statement' => [
'statements' => [
'declare',
'for',
'return',
'throw',
'try',
],
],
*/
])
->setFinder($finder);
return $config;
+37
View File
@@ -0,0 +1,37 @@
<?php
$finder = PhpCsFixer\Finder::create()
->in('app')
->in('config');
return PhpCsFixer\Config::create()
->setHideProgress(true)
->setUsingCache(false)
->setRiskyAllowed(true)
->setRules([
'@PSR2' => true,
'strict_param' => true,
'no_php4_constructor' => true,
'no_extra_blank_lines' => true,
'no_superfluous_elseif' => true,
'single_line_comment_style' => false,
'simple_to_complex_string_variable' => true,
'array_syntax' => [
'syntax' => 'short',
],
'binary_operator_spaces' => [
'align_double_arrow' => true,
],
/*
'blank_line_before_statement' => [
'statements' => [
'declare',
'for',
'return',
'throw',
'try',
],
],
*/
])
->setFinder($finder);
+6 -11
View File
@@ -1,11 +1,8 @@
FROM php:8.0.9-fpm-alpine3.14 FROM php:7.4-fpm-alpine
WORKDIR /var/www/ WORKDIR /var/www/
# Setup composer RUN apk add gmp-dev icu-dev zlib-dev libpng-dev
COPY --from=composer:2.1.5 /usr/bin/composer /usr/local/bin/composer
RUN apk add gmp-dev icu-dev zlib-dev libpng-dev libzip-dev zip
RUN curl --silent --show-error https://getcomposer.org/installer | php RUN curl --silent --show-error https://getcomposer.org/installer | php
# Copy any config files in # Copy any config files in
@@ -19,19 +16,17 @@ RUN docker-php-ext-install \
pdo_mysql \ pdo_mysql \
gd \ gd \
gmp \ gmp \
bcmath \ opcache && \
opcache \ docker-php-ext-enable pdo_mysql opcache
zip && \
docker-php-ext-enable pdo_mysql opcache bcmath zip
COPY . /var/www/ COPY . /var/www/
RUN composer install \ RUN php composer.phar install \
--ignore-platform-reqs \ --ignore-platform-reqs \
--no-interaction \ --no-interaction \
--no-plugins \ --no-plugins \
--no-scripts \ --no-scripts \
--prefer-dist --prefer-dist
#RUN chown -R www-data:www-data /var/www RUN chown -R www-data:www-data /var/www
EXPOSE 9000 EXPOSE 9000
+2 -3
View File
@@ -1,3 +1,5 @@
BSD 3-Clause License
Copyright (c) 2017, phpvms - http://www.phpvms.net Copyright (c) 2017, phpvms - http://www.phpvms.net
All rights reserved. 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 contributors may be used to endorse or promote products derived from
this software without specific prior written permission. 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" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+10 -1
View File
@@ -82,6 +82,10 @@ test:
phpcs: phpcs:
@vendor/bin/php-cs-fixer fix --config=.php_cs -v --diff --diff-format=udiff --dry-run @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 .PHONY: replay-acars
replay-acars: replay-acars:
#@php artisan phpvms:replay AAL10,AAL3113,BAW172,DAL988,FIN6,MSR986 --manual #@php artisan phpvms:replay AAL10,AAL3113,BAW172,DAL988,FIN6,MSR986 --manual
@@ -91,6 +95,11 @@ replay-acars:
sass-watch: sass-watch:
sass --watch public/assets/admin/sass/paper-dashboard.scss:public/assets/admin/css/paper-dashboard.css 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 .PHONY: deploy-package
deploy-package: deploy-package:
./.travis/deploy_script.sh ./.travis/deploy_script.sh
@@ -102,7 +111,7 @@ reset-installer:
.PHONY: docker-test .PHONY: docker-test
docker-test: docker-test:
@docker compose -f docker-compose.yml -f docker-compose.local.yml up @docker-compose -f docker-compose.yml -f docker-compose.local.yml up
.PHONY: docker-clean .PHONY: docker-clean
docker-clean: docker-clean:
+1 -5
View File
@@ -22,11 +22,7 @@ class ProcessQueue extends Command
'--stop-when-empty' => null, '--stop-when-empty' => null,
]); ]);
$jobOutput = trim(Artisan::output()); Log::info(Artisan::output());
if (!empty($jobOutput)) {
Log::info($jobOutput);
}
///** @var App\Support\WorkCommand $queueWorker */ ///** @var App\Support\WorkCommand $queueWorker */
//$queueWorker = new App\Support\WorkCommand(app('queue.worker'), app('cache.store')); //$queueWorker = new App\Support\WorkCommand(app('queue.worker'), app('cache.store'));
-90
View File
@@ -1,90 +0,0 @@
<?php
/**
* This runs any of the cron tasks that are set to run according to the Laravel schedule
*/
namespace App\Console;
use App\Console\Cron\FifteenMinute;
use App\Console\Cron\FiveMinute;
use App\Console\Cron\Hourly;
use App\Console\Cron\JobQueue;
use App\Console\Cron\Monthly;
use App\Console\Cron\Nightly;
use App\Console\Cron\ThirtyMinute;
use App\Console\Cron\Weekly;
use App\Contracts\Command;
use Illuminate\Console\Scheduling\Schedule;
class Cron
{
/** @var Schedule */
private $scheduler;
/**
* @var string[] The cron tasks which get called/run
*/
private $cronTasks = [
JobQueue::class,
FiveMinute::class,
FifteenMinute::class,
ThirtyMinute::class,
Hourly::class,
Nightly::class,
Weekly::class,
Monthly::class,
];
/**
* @var array Stores the instantiated cron tasks
*/
private $cronRunners = [];
/**
* @param Schedule $scheduler
*/
public function __construct(Schedule $scheduler)
{
$this->scheduler = $scheduler;
foreach ($this->cronTasks as $task) {
/** @var Command $cronTask */
$cronTask = app($task);
$signature = $cronTask->getSignature();
if (empty($signature)) {
continue;
}
$this->cronRunners[$signature] = $cronTask;
}
}
/**
* Try to figure out which commands are supposed to run right now
*
* @return array string of tasks that were run
*/
public function run(): array
{
$events = $this->scheduler->dueEvents(app());
if (empty($events)) {
return [];
}
$run = [];
/** @var \Illuminate\Console\Scheduling\Event $event */
foreach ($events as $event) {
foreach ($this->cronRunners as $signature => $task) {
if (!str_contains($event->command, $signature)) {
continue;
}
$task->callEvent();
$run[] = $signature;
}
}
return $run;
}
}
-26
View File
@@ -1,26 +0,0 @@
<?php
namespace App\Console\Cron;
use App\Contracts\CronCommand;
use App\Events\CronFifteenMinute;
/**
* The actual cron tasks are in app/Cron
*/
class FifteenMinute extends CronCommand
{
protected $signature = 'cron:fifteen';
protected $description = 'Run the 15 minute cron tasks';
protected $schedule;
public function handle(): void
{
$this->callEvent();
}
public function callEvent()
{
event(new CronFifteenMinute());
}
}
-29
View File
@@ -1,29 +0,0 @@
<?php
namespace App\Console\Cron;
use App\Contracts\CronCommand;
use App\Events\CronFiveMinute;
/**
* This just calls the CronNightly event, so all of the
* listeners, etc can just be called to run those tasks
*
* The actual cron tasks are in app/Cron
*/
class FiveMinute extends CronCommand
{
protected $signature = 'cron:five';
protected $description = 'Run the 5 minute cron tasks';
protected $schedule;
public function handle(): void
{
$this->callEvent();
}
public function callEvent()
{
event(new CronFiveMinute());
}
}
+3 -7
View File
@@ -2,14 +2,14 @@
namespace App\Console\Cron; namespace App\Console\Cron;
use App\Contracts\CronCommand; use App\Contracts\Command;
use App\Events\CronHourly; use App\Events\CronHourly;
/** /**
* This just calls the CronHourly event, so all of the * This just calls the CronHourly event, so all of the
* listeners, etc can just be called to run those tasks * listeners, etc can just be called to run those tasks
*/ */
class Hourly extends CronCommand class Hourly extends Command
{ {
protected $signature = 'cron:hourly'; protected $signature = 'cron:hourly';
protected $description = 'Run the hourly cron tasks'; protected $description = 'Run the hourly cron tasks';
@@ -17,11 +17,7 @@ class Hourly extends CronCommand
public function handle(): void public function handle(): void
{ {
$this->callEvent(); $this->redirectLoggingToFile('cron');
}
public function callEvent()
{
event(new CronHourly()); event(new CronHourly());
} }
} }
+5 -12
View File
@@ -2,14 +2,14 @@
namespace App\Console\Cron; namespace App\Console\Cron;
use App\Contracts\CronCommand; use App\Contracts\Command;
use Illuminate\Support\Facades\Artisan; use Illuminate\Support\Facades\Artisan;
/** /**
* This just calls the CronHourly event, so all of the * This just calls the CronHourly event, so all of the
* listeners, etc can just be called to run those tasks * listeners, etc can just be called to run those tasks
*/ */
class JobQueue extends CronCommand class JobQueue extends Command
{ {
protected $signature = 'cron:queue'; protected $signature = 'cron:queue';
protected $description = 'Run the cron queue tasks'; protected $description = 'Run the cron queue tasks';
@@ -17,16 +17,9 @@ class JobQueue extends CronCommand
public function handle(): void public function handle(): void
{ {
$this->callEvent(); $this->redirectLoggingToFile('cron');
$queueOutput = trim(Artisan::output());
if (!empty($queueOutput)) {
$this->info($queueOutput);
}
}
public function callEvent()
{
Artisan::call('queue:cron'); Artisan::call('queue:cron');
$this->info(Artisan::output());
} }
} }
+3 -7
View File
@@ -2,7 +2,7 @@
namespace App\Console\Cron; namespace App\Console\Cron;
use App\Contracts\CronCommand; use App\Contracts\Command;
use App\Events\CronMonthly; use App\Events\CronMonthly;
/** /**
@@ -11,7 +11,7 @@ use App\Events\CronMonthly;
* *
* The actual cron tasks are in app/Cron * The actual cron tasks are in app/Cron
*/ */
class Monthly extends CronCommand class Monthly extends Command
{ {
protected $signature = 'cron:monthly'; protected $signature = 'cron:monthly';
protected $description = 'Run the monthly cron tasks'; protected $description = 'Run the monthly cron tasks';
@@ -19,11 +19,7 @@ class Monthly extends CronCommand
public function handle(): void public function handle(): void
{ {
$this->callEvent(); $this->redirectLoggingToFile('cron');
}
public function callEvent()
{
event(new CronMonthly()); event(new CronMonthly());
} }
} }
+3 -7
View File
@@ -2,7 +2,7 @@
namespace App\Console\Cron; namespace App\Console\Cron;
use App\Contracts\CronCommand; use App\Contracts\Command;
use App\Events\CronNightly; use App\Events\CronNightly;
/** /**
@@ -11,7 +11,7 @@ use App\Events\CronNightly;
* *
* The actual cron tasks are in app/Cron * The actual cron tasks are in app/Cron
*/ */
class Nightly extends CronCommand class Nightly extends Command
{ {
protected $signature = 'cron:nightly'; protected $signature = 'cron:nightly';
protected $description = 'Run the nightly cron tasks'; protected $description = 'Run the nightly cron tasks';
@@ -19,11 +19,7 @@ class Nightly extends CronCommand
public function handle(): void public function handle(): void
{ {
$this->callEvent(); $this->redirectLoggingToFile('cron');
}
public function callEvent()
{
event(new CronNightly()); event(new CronNightly());
} }
} }
-26
View File
@@ -1,26 +0,0 @@
<?php
namespace App\Console\Cron;
use App\Contracts\CronCommand;
use App\Events\CronThirtyMinute;
/**
* The actual cron tasks are in app/Cron
*/
class ThirtyMinute extends CronCommand
{
protected $signature = 'cron:thirty';
protected $description = 'Run the 30 minute cron tasks';
protected $schedule;
public function handle(): void
{
$this->callEvent();
}
public function callEvent()
{
event(new CronThirtyMinute());
}
}
+3 -7
View File
@@ -2,7 +2,7 @@
namespace App\Console\Cron; namespace App\Console\Cron;
use App\Contracts\CronCommand; use App\Contracts\Command;
use App\Events\CronWeekly; use App\Events\CronWeekly;
/** /**
@@ -11,7 +11,7 @@ use App\Events\CronWeekly;
* *
* The actual cron tasks are in app/Cron * The actual cron tasks are in app/Cron
*/ */
class Weekly extends CronCommand class Weekly extends Command
{ {
protected $signature = 'cron:weekly'; protected $signature = 'cron:weekly';
protected $description = 'Run the weekly cron tasks'; protected $description = 'Run the weekly cron tasks';
@@ -19,11 +19,7 @@ class Weekly extends CronCommand
public function handle(): void public function handle(): void
{ {
$this->callEvent(); $this->redirectLoggingToFile('cron');
}
public function callEvent()
{
event(new CronWeekly()); event(new CronWeekly());
} }
} }
+1 -10
View File
@@ -2,13 +2,10 @@
namespace App\Console; namespace App\Console;
use App\Console\Cron\FifteenMinute;
use App\Console\Cron\FiveMinute;
use App\Console\Cron\Hourly; use App\Console\Cron\Hourly;
use App\Console\Cron\JobQueue; use App\Console\Cron\JobQueue;
use App\Console\Cron\Monthly; use App\Console\Cron\Monthly;
use App\Console\Cron\Nightly; use App\Console\Cron\Nightly;
use App\Console\Cron\ThirtyMinute;
use App\Console\Cron\Weekly; use App\Console\Cron\Weekly;
use App\Services\CronService; use App\Services\CronService;
use Illuminate\Console\Scheduling\Schedule; use Illuminate\Console\Scheduling\Schedule;
@@ -36,16 +33,10 @@ class Kernel extends ConsoleKernel
->withoutOverlapping(); ->withoutOverlapping();
} }
/*
* NOTE: IF MORE TASKS ARE ADDED, THEY ALSO MUST BE ADDED TO THE CRON.PHP
*/
$schedule->command(FiveMinute::class)->everyFiveMinutes();
$schedule->command(FifteenMinute::class)->everyFifteenMinutes();
$schedule->command(ThirtyMinute::class)->everyThirtyMinutes();
$schedule->command(Nightly::class)->dailyAt('01:00'); $schedule->command(Nightly::class)->dailyAt('01:00');
$schedule->command(Hourly::class)->hourly();
$schedule->command(Weekly::class)->weeklyOn(0); $schedule->command(Weekly::class)->weeklyOn(0);
$schedule->command(Monthly::class)->monthlyOn(1); $schedule->command(Monthly::class)->monthlyOn(1);
$schedule->command(Hourly::class)->hourly();
// When spatie-backups runs // When spatie-backups runs
/*if (config('backup.backup.enabled', false) === true) { /*if (config('backup.backup.enabled', false) === true) {
-10
View File
@@ -29,16 +29,6 @@ abstract class Command extends \Illuminate\Console\Command
}*/ }*/
} }
/**
* Return the signature of the command
*
* @return string
*/
public function getSignature(): string
{
return $this->signature;
}
/** /**
* Splice the logger and replace the active handlers with the handlers from the * Splice the logger and replace the active handlers with the handlers from the
* a stack in config/logging.php * a stack in config/logging.php
+4 -5
View File
@@ -87,17 +87,16 @@ abstract class Controller extends \Illuminate\Routing\Controller
* *
* @return \Illuminate\Http\JsonResponse * @return \Illuminate\Http\JsonResponse
*/ */
public function message($message, $count = null, $attrs = []) public function message($message, $count = null)
{ {
$ret = [ $attrs = [
'message' => $message, 'message' => $message,
'attrs' => $attrs,
]; ];
if ($count !== null) { if ($count !== null) {
$ret['count'] = $count; $attrs['count'] = $count;
} }
return response()->json($ret); return response()->json($attrs);
} }
} }
-20
View File
@@ -1,20 +0,0 @@
<?php
namespace App\Contracts;
abstract class CronCommand extends Command
{
/**
* @return mixed
*/
abstract public function callEvent();
/**
* Adjust the logging depending on where we're running from
*/
public function __construct()
{
parent::__construct();
$this->redirectLoggingToFile('cron');
}
}
-26
View File
@@ -166,36 +166,10 @@ class ImportExport
return []; return [];
} }
if (strpos($split_values[0], '?') !== false) {
// This contains the query string, which turns it into a multi-level array
$query_str = explode('?', $split_values[0]);
$parent = trim($query_str[0]);
$children = [];
$kvp = explode('&', trim($query_str[1]));
foreach ($kvp as $items) {
if (!$items) {
continue;
}
$this->kvpToArray($items, $children);
}
$ret[$parent] = $children;
return $ret;
}
// This is not a query string, return it back untouched
return [$split_values[0]]; return [$split_values[0]];
} }
foreach ($split_values as $value) { foreach ($split_values as $value) {
$value = trim($value);
if ($value === '') {
continue;
}
// This isn't in the query string format, so it's // This isn't in the query string format, so it's
// just a straight key-value pair set // just a straight key-value pair set
if (strpos($value, '?') === false) { if (strpos($value, '?') === false) {
+21
View File
@@ -2,6 +2,7 @@
namespace App\Contracts; namespace App\Contracts;
use App\Notifications\Channels\Discord\DiscordMessage;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
@@ -25,4 +26,24 @@ class Notification extends \Illuminate\Notifications\Notification implements Sho
$this->channels = $notif_config[$klass];*/ $this->channels = $notif_config[$klass];*/
} }
/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
*
* @return array
*/
/*public function via($notifiable)
{
return $this->channels;
}*/
/**
* @return DiscordMessage|null
*/
public function toDiscordChannel($notifiable): ?DiscordMessage
{
return null;
}
} }
+1 -1
View File
@@ -20,7 +20,7 @@ class ClearExpiredSimbrief extends Listener
} }
/** /**
* @param CronHourly $event * @param \App\Events\CronNightly $event
*/ */
public function handle(CronHourly $event): void public function handle(CronHourly $event): void
{ {
+1 -5
View File
@@ -5,7 +5,6 @@ namespace App\Cron\Hourly;
use App\Contracts\Listener; use App\Contracts\Listener;
use App\Events\CronHourly; use App\Events\CronHourly;
use App\Models\Enums\PirepState; use App\Models\Enums\PirepState;
use App\Models\Enums\PirepStatus;
use App\Models\Pirep; use App\Models\Pirep;
use App\Services\PirepService; use App\Services\PirepService;
use Carbon\Carbon; use Carbon\Carbon;
@@ -39,10 +38,7 @@ class DeletePireps extends Listener
protected function deletePireps(int $expire_time_hours, int $state) protected function deletePireps(int $expire_time_hours, int $state)
{ {
$dt = Carbon::now('UTC')->subHours($expire_time_hours); $dt = Carbon::now('UTC')->subHours($expire_time_hours);
$pireps = Pirep::where('created_at', '<', $dt) $pireps = Pirep::where('created_at', '<', $dt)->where(['state' => $state])->get();
->where(['state' => $state])
->where('status', '<>', PirepStatus::PAUSED)
->get();
/** @var PirepService $pirepSvc */ /** @var PirepService $pirepSvc */
$pirepSvc = app(PirepService::class); $pirepSvc = app(PirepService::class);
@@ -6,7 +6,6 @@ use App\Contracts\Listener;
use App\Events\CronHourly; use App\Events\CronHourly;
use App\Events\PirepCancelled; use App\Events\PirepCancelled;
use App\Models\Enums\PirepState; use App\Models\Enums\PirepState;
use App\Models\Enums\PirepStatus;
use App\Models\Pirep; use App\Models\Pirep;
use Carbon\Carbon; use Carbon\Carbon;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
@@ -32,9 +31,7 @@ class RemoveExpiredLiveFlights extends Listener
$date = Carbon::now('UTC')->subHours(setting('acars.live_time')); $date = Carbon::now('UTC')->subHours(setting('acars.live_time'));
$pireps = Pirep::where('updated_at', '<', $date) $pireps = Pirep::where('updated_at', '<', $date)
->where('state', PirepState::IN_PROGRESS) ->where('state', PirepState::IN_PROGRESS)
->where('status', '<>', PirepStatus::PAUSED)
->get(); ->get();
foreach ($pireps as $pirep) { foreach ($pireps as $pirep) {
event(new PirepCancelled($pirep)); event(new PirepCancelled($pirep));
Log::info('Cron: Deleting Expired Live PIREP id='.$pirep->id.', state='.PirepState::label($pirep->state)); Log::info('Cron: Deleting Expired Live PIREP id='.$pirep->id.', state='.PirepState::label($pirep->state));
@@ -1,53 +0,0 @@
<?php
use App\Contracts\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddTypeRatingTables extends Migration
{
public function up()
{
if (!Schema::hasTable('typeratings')) {
Schema::create('typeratings', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('type');
$table->string('description')->nullable();
$table->string('image_url')->nullable();
$table->boolean('active')->default(true);
$table->timestamps();
$table->unique('id');
$table->unique('name');
});
}
if (!Schema::hasTable('typerating_user')) {
Schema::create('typerating_user', function (Blueprint $table) {
$table->unsignedInteger('typerating_id');
$table->unsignedInteger('user_id');
$table->primary(['typerating_id', 'user_id']);
$table->index(['typerating_id', 'user_id']);
});
}
if (!Schema::hasTable('typerating_subfleet')) {
Schema::create('typerating_subfleet', function (Blueprint $table) {
$table->unsignedInteger('typerating_id');
$table->unsignedInteger('subfleet_id');
$table->primary(['typerating_id', 'subfleet_id']);
$table->index(['typerating_id', 'subfleet_id']);
});
}
}
public function down()
{
Schema::dropIfExists('typeratings');
Schema::dropIfExists('typerating_user');
Schema::dropIfExists('typerating_subfleet');
}
}
@@ -1,15 +0,0 @@
<?php
use App\Contracts\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddHubToAircraft extends Migration
{
public function up()
{
Schema::table('aircraft', function (Blueprint $table) {
$table->string('hub_id', 5)->nullable()->after('airport_id');
});
}
}
@@ -1,15 +0,0 @@
<?php
use App\Contracts\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class UpdateAwardsAddActive extends Migration
{
public function up()
{
Schema::table('awards', function (Blueprint $table) {
$table->boolean('active')->default(true)->nullable()->after('ref_model_params');
});
}
}
@@ -1,15 +0,0 @@
<?php
use App\Contracts\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class UpdateUsersAddNotes extends Migration
{
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->mediumText('notes')->nullable()->after('remember_token');
});
}
}
+9 -18
View File
@@ -36,8 +36,7 @@ acars:
sim_time: now sim_time: now
created_at: 'now' created_at: 'now'
updated_at: 'now' updated_at: 'now'
- id: 9aAN4mxlK9zb1 - pirep_id: b68R5gwVzpVe
pirep_id: b68R5gwVzpVe
type: '0' type: '0'
nav_type: null nav_type: null
order: '0' order: '0'
@@ -55,8 +54,7 @@ acars:
sim_time: now sim_time: now
created_at: 'now' created_at: 'now'
updated_at: 'now' updated_at: 'now'
- id: 9aAN4mxlK9zb2 - pirep_id: b68R5gwVzpVe
pirep_id: b68R5gwVzpVe
type: '0' type: '0'
nav_type: null nav_type: null
order: '0' order: '0'
@@ -74,8 +72,7 @@ acars:
sim_time: now sim_time: now
created_at: 'now' created_at: 'now'
updated_at: 'now' updated_at: 'now'
- id: 9aAN4mxlK9zb3 - pirep_id: b68R5gwVzpVe
pirep_id: b68R5gwVzpVe
type: '0' type: '0'
nav_type: null nav_type: null
order: '0' order: '0'
@@ -93,8 +90,7 @@ acars:
sim_time: now sim_time: now
created_at: 'now' created_at: 'now'
updated_at: 'now' updated_at: 'now'
- id: 9aAN4mxlK9zb34 - pirep_id: b68R5gwVzpVe
pirep_id: b68R5gwVzpVe
type: '0' type: '0'
nav_type: null nav_type: null
order: '0' order: '0'
@@ -112,8 +108,7 @@ acars:
sim_time: now sim_time: now
created_at: 'now' created_at: 'now'
updated_at: 'now' updated_at: 'now'
- id: 9aAN4mxlK9zb35 - pirep_id: b68R5gwVzpVe
pirep_id: b68R5gwVzpVe
type: '0' type: '0'
nav_type: null nav_type: null
order: '0' order: '0'
@@ -131,8 +126,7 @@ acars:
sim_time: now sim_time: now
created_at: 'now' created_at: 'now'
updated_at: 'now' updated_at: 'now'
- id: 9aAN4mxlK9zb36 - pirep_id: b68R5gwVzpVe
pirep_id: b68R5gwVzpVe
type: '0' type: '0'
nav_type: null nav_type: null
order: '0' order: '0'
@@ -150,8 +144,7 @@ acars:
sim_time: now sim_time: now
created_at: 'now' created_at: 'now'
updated_at: 'now' updated_at: 'now'
- id: 9aAN4mxlK9zb37 - pirep_id: b68R5gwVzpVe
pirep_id: b68R5gwVzpVe
type: '0' type: '0'
nav_type: null nav_type: null
order: '0' order: '0'
@@ -169,8 +162,7 @@ acars:
sim_time: now sim_time: now
created_at: 'now' created_at: 'now'
updated_at: 'now' updated_at: 'now'
- id: 9aAN4mxlK9zb38 - pirep_id: b68R5gwVzpVe
pirep_id: b68R5gwVzpVe
type: '0' type: '0'
nav_type: null nav_type: null
order: '0' order: '0'
@@ -188,8 +180,7 @@ acars:
sim_time: now sim_time: now
created_at: 'now' created_at: 'now'
updated_at: 'now' updated_at: 'now'
- id: 9aAN4mxlK9zb39 - pirep_id: b68R5gwVzpVe
pirep_id: b68R5gwVzpVe
type: '0' type: '0'
nav_type: null nav_type: null
order: '0' order: '0'
-52
View File
@@ -34,28 +34,6 @@ airports:
lon: -97.6698889 lon: -97.6698889
hub: 1 hub: 1
ground_handling_cost: 100 ground_handling_cost: 100
- id: KHPN
iata: HPN
icao: KHPN
name: Westchester County Airport
location: White Plains
country: United States
timezone: America/New_York
lat: 41.067
lon: -73.7076
hub: 1
ground_handling_cost: 100
- id: KLGA
iata: LGA
icao: KLGA
name: La Guardia Airport
location: New York, New York, USA
country: United States
timezone: America/New_York
lat: 40.7772
lon: -73.8726
hub: 1
ground_handling_cost: 250
- id: KJFK - id: KJFK
iata: JFK iata: JFK
icao: KJFK icao: KJFK
@@ -470,21 +448,6 @@ flights:
- id: flightid_1 - id: flightid_1
airline_id: 1 airline_id: 1
flight_number: 100 flight_number: 100
dpt_airport_id: KHPN
arr_airport_id: KJFK
route: DCT CMK V374 DENNA V44 BELTT/N0346F140 V44 DPK DCT
distance: 113
level: 110
dpt_time: 6PM CST
arr_time: 11PM EST
flight_time: 240
flight_type: J
load_factor: 100
created_at: NOW
updated_at: NOW
- id: flightid_2
airline_id: 1
flight_number: 101
dpt_airport_id: KAUS dpt_airport_id: KAUS
arr_airport_id: KJFK arr_airport_id: KJFK
route: KAUS SID TNV J87 IAH J2 LCH J22 MEI J239 ATL J52 AJFEB J14 BYJAC Q60 JAXSN J14 COLIN J61 HUBBS J55 SIE STAR KJFK route: KAUS SID TNV J87 IAH J2 LCH J22 MEI J239 ATL J52 AJFEB J14 BYJAC Q60 JAXSN J14 COLIN J61 HUBBS J55 SIE STAR KJFK
@@ -586,21 +549,6 @@ flights:
visible: 1 visible: 1
created_at: now created_at: now
updated_at: now updated_at: now
- id: flightid_4
airline_id: 1
flight_number: 100
dpt_airport_id: KHPN
arr_airport_id: KLGA
route: DCT CMK V374 DENNA V44 BELTT/N0346F140 V44 DPK DCT
distance: 75
level: 110
dpt_time: 6PM CST
arr_time: 11PM EST
flight_time: 240
flight_type: J
load_factor: 100
created_at: NOW
updated_at: NOW
flight_fields: flight_fields:
- name: Departure Terminal - name: Departure Terminal
File diff suppressed because one or more lines are too long
-3
View File
@@ -42,9 +42,6 @@
- name: ranks - name: ranks
display_name: Ranks display_name: Ranks
description: Create/edit ranks description: Create/edit ranks
- name: typeratings
display_name: Type Ratings
description: Create/edit type ratings
- name: users - name: users
display_name: Users display_name: Users
description: Create/edit users description: Create/edit users
+1 -57
View File
@@ -137,13 +137,6 @@
options: '' options: ''
type: int type: int
description: 'Initial zoom level on the map' description: 'Initial zoom level on the map'
- key: acars.update_interval
name: 'Refresh Interval'
group: acars
value: 60
options: ''
type: int
description: 'How often the live map updates its data'
- key: airports.default_ground_handling_cost - key: airports.default_ground_handling_cost
name: 'Default Ground Handling Cost' name: 'Default Ground Handling Cost'
group: airports group: airports
@@ -290,14 +283,7 @@
value: true value: true
options: '' options: ''
type: boolean type: boolean
description: 'Aircraft restricted to user''s rank' description: 'Aircraft that can be flown are restricted to a user''s rank'
- key: pireps.restrict_aircraft_to_typerating
name: 'Restrict Aircraft by Type Ratings'
group: pireps
value: false
options: ''
type: boolean
description: 'Aircraft restricted to user type ratings'
- key: pireps.only_aircraft_at_dpt_airport - key: pireps.only_aircraft_at_dpt_airport
name: 'Restrict Aircraft At Departure' name: 'Restrict Aircraft At Departure'
group: pireps group: pireps
@@ -333,13 +319,6 @@
options: '' options: ''
type: int type: int
description: 'The length of a pilot''s ID' description: 'The length of a pilot''s ID'
- key: pilots.id_code
name: 'Pilot ID Code'
group: pilots
value: ''
options: ''
type: text
description: 'Fixed ICAO code for pilot IDs'
- key: pilots.auto_accept - key: pilots.auto_accept
name: 'Auto Accept New Pilot' name: 'Auto Accept New Pilot'
group: pilots group: pilots
@@ -410,41 +389,6 @@
options: '' options: ''
type: text type: text
description: The Discord Webhook URL for private notifications description: The Discord Webhook URL for private notifications
- key: notifications.discord_pirep_status
name: Discord Pirep Messages (Public)
group: notifications
value: true
options: ''
type: boolean
description: Pirep status messages (Only key events are being sent)
- key: notifications.mail_pirep_admin
name: Pirep Filed (Admin)
group: notifications
value: true
options: ''
type: boolean
description: Pirep filed mails sent to admins
- key: notifications.mail_pirep_user_ack
name: Pirep Accepted (Pilot)
group: notifications
value: true
options: ''
type: boolean
description: Pirep Accepted mails sent to pilots
- key: notifications.mail_pirep_user_rej
name: Pirep Rejected (Pilot)
group: notifications
value: true
options: ''
type: boolean
description: Pirep Rejected mails sent to pilots
- key: notifications.mail_news
name: News Mails
group: notifications
value: true
options: ''
type: boolean
description: News mails sent to all members
- key: 'cron.random_id' - key: 'cron.random_id'
name: 'Cron Randomized ID' name: 'Cron Randomized ID'
group: 'cron' group: 'cron'
-9
View File
@@ -1,9 +0,0 @@
<?php
namespace App\Events;
use App\Contracts\Event;
class CronFifteenMinute extends Event
{
}
-9
View File
@@ -1,9 +0,0 @@
<?php
namespace App\Events;
use App\Contracts\Event;
class CronFiveMinute extends Event
{
}
-9
View File
@@ -1,9 +0,0 @@
<?php
namespace App\Events;
use App\Contracts\Event;
class CronThirtyMinute extends Event
{
}
-39
View File
@@ -1,39 +0,0 @@
<?php
namespace App\Events;
use App\Contracts\Event;
use App\Models\Pirep;
/**
* This event is dispatched when the fares for a flight report
* are collected. Your listeners should return a list of Fare
* models. Don't call save on the model!
*
* Example return:
*
* new Fare([
* 'name' => '', # displayed as the memo
* 'type' => [INTEGER], # from FareType enum class
* 'price' => [DECIMAL],
* 'cost' => [DECIMAL], # optional
* 'notes' => '', # used as Transaction Group
* ]);
*
* The event caller will check the 'type' to make sure that it
* will filter out fares that only apply to the current process
*
* The event will have a copy of the PIREP model, if it's applicable
*/
class Fares extends Event
{
public $pirep;
/**
* @param Pirep|null $pirep
*/
public function __construct(Pirep $pirep = null)
{
$this->pirep = $pirep;
}
}
-43
View File
@@ -1,43 +0,0 @@
<?php
namespace App\Exceptions;
class BidNotFound extends AbstractHttpException
{
private $bid_id;
public function __construct($bid_id)
{
$this->bid_id = $bid_id;
parent::__construct(
404,
'The bid '.$bid_id.' was not found'
);
}
/**
* Return the RFC 7807 error type (without the URL root)
*/
public function getErrorType(): string
{
return 'bid-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 [
'bid_id' => $this->bid_id,
];
}
}
@@ -79,7 +79,6 @@ class AircraftController extends Controller
{ {
return view('admin.aircraft.create', [ return view('admin.aircraft.create', [
'airports' => $this->airportRepo->selectBoxList(), 'airports' => $this->airportRepo->selectBoxList(),
'hubs' => $this->airportRepo->selectBoxList(true, true),
'subfleets' => Subfleet::all()->pluck('name', 'id'), 'subfleets' => Subfleet::all()->pluck('name', 'id'),
'statuses' => AircraftStatus::select(false), 'statuses' => AircraftStatus::select(false),
'subfleet_id' => $request->query('subfleet'), 'subfleet_id' => $request->query('subfleet'),
@@ -144,7 +143,6 @@ class AircraftController extends Controller
return view('admin.aircraft.edit', [ return view('admin.aircraft.edit', [
'aircraft' => $aircraft, 'aircraft' => $aircraft,
'airports' => $this->airportRepo->selectBoxList(), 'airports' => $this->airportRepo->selectBoxList(),
'hubs' => $this->airportRepo->selectBoxList(true, true),
'subfleets' => Subfleet::all()->pluck('name', 'id'), 'subfleets' => Subfleet::all()->pluck('name', 'id'),
'statuses' => AircraftStatus::select(false), 'statuses' => AircraftStatus::select(false),
]); ]);
@@ -38,7 +38,7 @@ class AirlinesController extends Controller
public function index(Request $request) public function index(Request $request)
{ {
$this->airlineRepo->pushCriteria(new RequestCriteria($request)); $this->airlineRepo->pushCriteria(new RequestCriteria($request));
$airlines = $this->airlineRepo->orderby('name', 'asc')->get(); $airlines = $this->airlineRepo->all();
return view('admin.airlines.index', [ return view('admin.airlines.index', [
'airlines' => $airlines, 'airlines' => $airlines,
@@ -300,18 +300,14 @@ class FlightController extends Controller
public function export(Request $request) public function export(Request $request)
{ {
$exporter = app(ExportService::class); $exporter = app(ExportService::class);
$flights = $this->flightRepo->all();
$where = [];
$file_name = 'flights.csv';
if ($request->input('airline_id')) {
$airline_id = $request->input('airline_id');
$where['airline_id'] = $airline_id;
$file_name = 'flights-'.$airline_id.'.csv';
}
$flights = $this->flightRepo->where($where)->orderBy('airline_id')->orderBy('flight_number')->orderBy('route_code')->orderBy('route_leg')->get();
$path = $exporter->exportFlights($flights); $path = $exporter->exportFlights($flights);
return response()->download($path, $file_name, ['content-type' => 'text/csv'])->deleteFileAfterSend(true); return response()
->download($path, 'flights.csv', [
'content-type' => 'text/csv',
])
->deleteFileAfterSend(true);
} }
/** /**
@@ -9,7 +9,6 @@ use Illuminate\Contracts\View\Factory;
use Illuminate\Http\RedirectResponse; use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Routing\Redirector; use Illuminate\Routing\Redirector;
use Illuminate\Support\Facades\Log;
use Illuminate\View\View; use Illuminate\View\View;
class ModulesController extends Controller class ModulesController extends Controller
@@ -30,7 +29,6 @@ class ModulesController extends Controller
{ {
$modules = $this->moduleSvc->getAllModules(); $modules = $this->moduleSvc->getAllModules();
$new_modules = $this->moduleSvc->scan(); $new_modules = $this->moduleSvc->scan();
return view('admin.modules.index', [ return view('admin.modules.index', [
'modules' => $modules, 'modules' => $modules,
'new_modules' => $new_modules, 'new_modules' => $new_modules,
@@ -99,14 +97,7 @@ class ModulesController extends Controller
*/ */
public function enable(Request $request) public function enable(Request $request)
{ {
$moduleName = $request->input('name'); $this->moduleSvc->addModule($request->input('name'));
try {
$this->moduleSvc->addModule($moduleName);
} catch (\Exception $e) {
Log::error('Error activating module '.$moduleName);
}
return redirect(route('admin.modules.index')); return redirect(route('admin.modules.index'));
} }
@@ -9,7 +9,6 @@ use App\Models\Enums\PirepSource;
use App\Models\Enums\PirepState; use App\Models\Enums\PirepState;
use App\Models\Pirep; use App\Models\Pirep;
use App\Models\PirepComment; use App\Models\PirepComment;
use App\Models\PirepFare;
use App\Repositories\AircraftRepository; use App\Repositories\AircraftRepository;
use App\Repositories\AirlineRepository; use App\Repositories\AirlineRepository;
use App\Repositories\AirportRepository; use App\Repositories\AirportRepository;
@@ -152,10 +151,10 @@ class PirepController extends Controller
$count = $request->input($field_name); $count = $request->input($field_name);
} }
$fares[] = new PirepFare([ $fares[] = [
'fare_id' => $fare->id, 'fare_id' => $fare->id,
'count' => $count, 'count' => $count,
]); ];
} }
$this->fareSvc->saveForPirep($pirep, $fares); $this->fareSvc->saveForPirep($pirep, $fares);
+118 -196
View File
@@ -17,7 +17,6 @@ use App\Repositories\AircraftRepository;
use App\Repositories\FareRepository; use App\Repositories\FareRepository;
use App\Repositories\RankRepository; use App\Repositories\RankRepository;
use App\Repositories\SubfleetRepository; use App\Repositories\SubfleetRepository;
use App\Repositories\TypeRatingRepository;
use App\Services\ExportService; use App\Services\ExportService;
use App\Services\FareService; use App\Services\FareService;
use App\Services\FleetService; use App\Services\FleetService;
@@ -37,29 +36,26 @@ class SubfleetController extends Controller
private $importSvc; private $importSvc;
private $rankRepo; private $rankRepo;
private $subfleetRepo; private $subfleetRepo;
private $typeratingRepo;
/** /**
* SubfleetController constructor. * SubfleetController constructor.
* *
* @param AircraftRepository $aircraftRepo * @param AircraftRepository $aircraftRepo
* @param FareRepository $fareRepo * @param FleetService $fleetSvc
* @param FareService $fareSvc * @param FareRepository $fareRepo
* @param FleetService $fleetSvc * @param FareService $fareSvc
* @param ImportService $importSvc * @param ImportService $importSvc
* @param RankRepository $rankRepo * @param RankRepository $rankRepo
* @param SubfleetRepository $subfleetRepo * @param SubfleetRepository $subfleetRepo
* @param TypeRatingRepository $typeratingRepo
*/ */
public function __construct( public function __construct(
AircraftRepository $aircraftRepo, AircraftRepository $aircraftRepo,
FleetService $fleetSvc,
FareRepository $fareRepo, FareRepository $fareRepo,
FareService $fareSvc, FareService $fareSvc,
FleetService $fleetSvc,
ImportService $importSvc, ImportService $importSvc,
RankRepository $rankRepo, RankRepository $rankRepo,
SubfleetRepository $subfleetRepo, SubfleetRepository $subfleetRepo
TypeRatingRepository $typeratingRepo
) { ) {
$this->aircraftRepo = $aircraftRepo; $this->aircraftRepo = $aircraftRepo;
$this->fareRepo = $fareRepo; $this->fareRepo = $fareRepo;
@@ -68,7 +64,48 @@ class SubfleetController extends Controller
$this->importSvc = $importSvc; $this->importSvc = $importSvc;
$this->rankRepo = $rankRepo; $this->rankRepo = $rankRepo;
$this->subfleetRepo = $subfleetRepo; $this->subfleetRepo = $subfleetRepo;
$this->typeratingRepo = $typeratingRepo; }
/**
* Get the ranks that are available to the subfleet
*
* @param $subfleet
*
* @return array
*/
protected function getAvailRanks($subfleet)
{
$retval = [];
$all_ranks = $this->rankRepo->all();
$avail_ranks = $all_ranks->except($subfleet->ranks->modelKeys());
foreach ($avail_ranks as $rank) {
$retval[$rank->id] = $rank->name;
}
return $retval;
}
/**
* Get all the fares that haven't been assigned to a given subfleet
*
* @param mixed $subfleet
*
* @return array
*/
protected function getAvailFares($subfleet)
{
$retval = [];
$all_fares = $this->fareRepo->all();
$avail_fares = $all_fares->except($subfleet->fares->modelKeys());
foreach ($avail_fares as $fare) {
$retval[$fare->id] = $fare->name.
' (price: '.$fare->price.
', type: '.FareType::label($fare->type).
', cost: '.$fare->cost.
', capacity: '.$fare->capacity.')';
}
return $retval;
} }
/** /**
@@ -83,7 +120,7 @@ class SubfleetController extends Controller
public function index(Request $request) public function index(Request $request)
{ {
$this->subfleetRepo->with(['airline'])->pushCriteria(new RequestCriteria($request)); $this->subfleetRepo->with(['airline'])->pushCriteria(new RequestCriteria($request));
$subfleets = $this->subfleetRepo->orderby('name', 'asc')->get(); $subfleets = $this->subfleetRepo->all();
return view('admin.subfleets.index', [ return view('admin.subfleets.index', [
'subfleets' => $subfleets, 'subfleets' => $subfleets,
@@ -115,8 +152,8 @@ class SubfleetController extends Controller
{ {
$input = $request->all(); $input = $request->all();
$subfleet = $this->subfleetRepo->create($input); $subfleet = $this->subfleetRepo->create($input);
Flash::success('Subfleet saved successfully.');
Flash::success('Subfleet saved successfully.');
return redirect(route('admin.subfleets.edit', [$subfleet->id])); return redirect(route('admin.subfleets.edit', [$subfleet->id]));
} }
@@ -135,12 +172,10 @@ class SubfleetController extends Controller
if (empty($subfleet)) { if (empty($subfleet)) {
Flash::error('Subfleet not found'); Flash::error('Subfleet not found');
return redirect(route('admin.subfleets.index')); return redirect(route('admin.subfleets.index'));
} }
$avail_fares = $this->getAvailFares($subfleet); $avail_fares = $this->getAvailFares($subfleet);
return view('admin.subfleets.show', [ return view('admin.subfleets.show', [
'subfleet' => $subfleet, 'subfleet' => $subfleet,
'avail_fares' => $avail_fares, 'avail_fares' => $avail_fares,
@@ -157,27 +192,24 @@ class SubfleetController extends Controller
public function edit($id) public function edit($id)
{ {
$subfleet = $this->subfleetRepo $subfleet = $this->subfleetRepo
->with(['fares', 'ranks', 'typeratings']) ->with(['fares', 'ranks'])
->findWithoutFail($id); ->findWithoutFail($id);
if (empty($subfleet)) { if (empty($subfleet)) {
Flash::error('Subfleet not found'); Flash::error('Subfleet not found');
return redirect(route('admin.subfleets.index')); return redirect(route('admin.subfleets.index'));
} }
$avail_fares = $this->getAvailFares($subfleet); $avail_fares = $this->getAvailFares($subfleet);
$avail_ranks = $this->getAvailRanks($subfleet); $avail_ranks = $this->getAvailRanks($subfleet);
$avail_ratings = $this->getAvailTypeRatings($subfleet);
return view('admin.subfleets.edit', [ return view('admin.subfleets.edit', [
'airlines' => Airline::all()->pluck('name', 'id'), 'airlines' => Airline::all()->pluck('name', 'id'),
'hubs' => Airport::where('hub', 1)->pluck('name', 'id'), 'hubs' => Airport::where('hub', 1)->pluck('name', 'id'),
'fuel_types' => FuelType::labels(), 'fuel_types' => FuelType::labels(),
'avail_fares' => $avail_fares, 'avail_fares' => $avail_fares,
'avail_ranks' => $avail_ranks, 'avail_ranks' => $avail_ranks,
'avail_ratings' => $avail_ratings, 'subfleet' => $subfleet,
'subfleet' => $subfleet,
]); ]);
} }
@@ -197,13 +229,12 @@ class SubfleetController extends Controller
if (empty($subfleet)) { if (empty($subfleet)) {
Flash::error('Subfleet not found'); Flash::error('Subfleet not found');
return redirect(route('admin.subfleets.index')); return redirect(route('admin.subfleets.index'));
} }
$this->subfleetRepo->update($request->all(), $id); $this->subfleetRepo->update($request->all(), $id);
Flash::success('Subfleet updated successfully.');
Flash::success('Subfleet updated successfully.');
return redirect(route('admin.subfleets.index')); return redirect(route('admin.subfleets.index'));
} }
@@ -220,7 +251,6 @@ class SubfleetController extends Controller
if (empty($subfleet)) { if (empty($subfleet)) {
Flash::error('Subfleet not found'); Flash::error('Subfleet not found');
return redirect(route('admin.subfleets.index')); return redirect(route('admin.subfleets.index'));
} }
@@ -229,13 +259,12 @@ class SubfleetController extends Controller
$aircraft = $this->aircraftRepo->findWhere(['subfleet_id' => $id], ['id']); $aircraft = $this->aircraftRepo->findWhere(['subfleet_id' => $id], ['id']);
if ($aircraft->count() > 0) { if ($aircraft->count() > 0) {
Flash::error('There are aircraft still assigned to this subfleet, you can\'t delete it!')->important(); Flash::error('There are aircraft still assigned to this subfleet, you can\'t delete it!')->important();
return redirect(route('admin.subfleets.index')); return redirect(route('admin.subfleets.index'));
} }
$this->subfleetRepo->delete($id); $this->subfleetRepo->delete($id);
Flash::success('Subfleet deleted successfully.');
Flash::success('Subfleet deleted successfully.');
return redirect(route('admin.subfleets.index')); return redirect(route('admin.subfleets.index'));
} }
@@ -252,8 +281,11 @@ class SubfleetController extends Controller
$subfleets = $this->subfleetRepo->all(); $subfleets = $this->subfleetRepo->all();
$path = $exporter->exportSubfleets($subfleets); $path = $exporter->exportSubfleets($subfleets);
return response()
return response()->download($path, 'subfleets.csv', ['content-type' => 'text/csv'])->deleteFileAfterSend(true); ->download($path, 'subfleets.csv', [
'content-type' => 'text/csv',
])
->deleteFileAfterSend(true);
} }
/** /**
@@ -280,64 +312,77 @@ class SubfleetController extends Controller
} }
/** /**
* Get all the fares that haven't been assigned to a given subfleet * @param Subfleet $subfleet
* *
* @param mixed $subfleet * @return mixed
*
* @return array
*/ */
protected function getAvailFares($subfleet) protected function return_ranks_view(?Subfleet $subfleet)
{ {
$retval = []; $subfleet->refresh();
$all_fares = $this->fareRepo->all();
$avail_fares = $all_fares->except($subfleet->fares->modelKeys());
foreach ($avail_fares as $fare) {
$retval[$fare->id] = $fare->name.
' (price: '.$fare->price.
', type: '.FareType::label($fare->type).
', cost: '.$fare->cost.
', capacity: '.$fare->capacity.')';
}
return $retval; $avail_ranks = $this->getAvailRanks($subfleet);
return view('admin.subfleets.ranks', [
'subfleet' => $subfleet,
'avail_ranks' => $avail_ranks,
]);
} }
/** /**
* Get the ranks that are available to the subfleet * @param Subfleet $subfleet
* *
* @param $subfleet * @return mixed
*
* @return array
*/ */
protected function getAvailRanks($subfleet) protected function return_fares_view(?Subfleet $subfleet)
{ {
$retval = []; $subfleet->refresh();
$all_ranks = $this->rankRepo->all();
$avail_ranks = $all_ranks->except($subfleet->ranks->modelKeys());
foreach ($avail_ranks as $rank) {
$retval[$rank->id] = $rank->name;
}
return $retval; $avail_fares = $this->getAvailFares($subfleet);
return view('admin.subfleets.fares', [
'subfleet' => $subfleet,
'avail_fares' => $avail_fares,
]);
} }
/** /**
* Get the type ratings that are available to the subfleet * Operations for associating ranks to the subfleet
* *
* @param $subfleet * @param $id
* @param Request $request
* *
* @return array * @return mixed
*/ */
protected function getAvailTypeRatings($subfleet) public function ranks($id, Request $request)
{ {
$retval = []; $subfleet = $this->subfleetRepo->findWithoutFail($id);
$all_ratings = $this->typeratingRepo->all(); if (empty($subfleet)) {
$avail_ratings = $all_ratings->except($subfleet->typeratings->modelKeys()); return $this->return_ranks_view($subfleet);
foreach ($avail_ratings as $tr) {
$retval[$tr->id] = $tr->name.' ('.$tr->type.')';
} }
return $retval; if ($request->isMethod('get')) {
return $this->return_ranks_view($subfleet);
}
/*
* update specific rank data
*/
if ($request->isMethod('post')) {
$rank = $this->rankRepo->find($request->input('rank_id'));
$this->fleetSvc->addSubfleetToRank($subfleet, $rank);
} elseif ($request->isMethod('put')) {
$override = [];
$rank = $this->rankRepo->find($request->input('rank_id'));
$override[$request->name] = $request->value;
$this->fleetSvc->addSubfleetToRank($subfleet, $rank, $override);
} // dissassociate fare from teh aircraft
elseif ($request->isMethod('delete')) {
$rank = $this->rankRepo->find($request->input('rank_id'));
$this->fleetSvc->removeSubfleetFromRank($subfleet, $rank);
}
$subfleet->save();
return $this->return_ranks_view($subfleet);
} }
/** /**
@@ -353,54 +398,6 @@ class SubfleetController extends Controller
]); ]);
} }
/**
* @param Subfleet $subfleet
*
* @return mixed
*/
protected function return_fares_view(?Subfleet $subfleet)
{
$subfleet->refresh();
$avail_fares = $this->getAvailFares($subfleet);
return view('admin.subfleets.fares', [
'subfleet' => $subfleet,
'avail_fares' => $avail_fares,
]);
}
/**
* @param Subfleet $subfleet
*
* @return mixed
*/
protected function return_ranks_view(?Subfleet $subfleet)
{
$subfleet->refresh();
$avail_ranks = $this->getAvailRanks($subfleet);
return view('admin.subfleets.ranks', [
'subfleet' => $subfleet,
'avail_ranks' => $avail_ranks,
]);
}
/**
* @param Subfleet $subfleet
*
* @return mixed
*/
protected function return_typeratings_view(?Subfleet $subfleet)
{
$subfleet->refresh();
$avail_ratings = $this->getAvailTypeRatings($subfleet);
return view('admin.subfleets.type_ratings', [
'subfleet' => $subfleet,
'avail_ratings' => $avail_ratings,
]);
}
/** /**
* Operations for associating ranks to the subfleet * Operations for associating ranks to the subfleet
* *
@@ -482,79 +479,4 @@ class SubfleetController extends Controller
return $this->return_fares_view($subfleet); return $this->return_fares_view($subfleet);
} }
/**
* Operations for associating ranks to the subfleet
*
* @param $id
* @param Request $request
*
* @return mixed
*/
public function ranks($id, Request $request)
{
$subfleet = $this->subfleetRepo->findWithoutFail($id);
if (empty($subfleet)) {
return $this->return_ranks_view($subfleet);
}
if ($request->isMethod('get')) {
return $this->return_ranks_view($subfleet);
}
// associate rank with the subfleet
if ($request->isMethod('post')) {
$rank = $this->rankRepo->find($request->input('rank_id'));
$this->fleetSvc->addSubfleetToRank($subfleet, $rank);
} // override definitions
elseif ($request->isMethod('put')) {
$override = [];
$rank = $this->rankRepo->find($request->input('rank_id'));
$override[$request->name] = $request->value;
$this->fleetSvc->addSubfleetToRank($subfleet, $rank, $override);
} // dissassociate rank from the subfleet
elseif ($request->isMethod('delete')) {
$rank = $this->rankRepo->find($request->input('rank_id'));
$this->fleetSvc->removeSubfleetFromRank($subfleet, $rank);
}
$subfleet->save();
return $this->return_ranks_view($subfleet);
}
/**
* Operations for associating type ratings to the subfleet
*
* @param $id
* @param Request $request
*
* @return mixed
*/
public function typeratings($id, Request $request)
{
$subfleet = $this->subfleetRepo->findWithoutFail($id);
if (empty($subfleet)) {
return $this->return_typeratings_view($subfleet);
}
if ($request->isMethod('get')) {
return $this->return_typeratings_view($subfleet);
}
// associate subfleet with type rating
if ($request->isMethod('post')) {
$typerating = $this->typeratingRepo->find($request->input('typerating_id'));
$this->fleetSvc->addSubfleetToTypeRating($subfleet, $typerating);
} // dissassociate subfleet from the type rating
elseif ($request->isMethod('delete')) {
$typerating = $this->typeratingRepo->find($request->input('typerating_id'));
$this->fleetSvc->removeSubfleetFromTypeRating($subfleet, $typerating);
}
$subfleet->save();
return $this->return_typeratings_view($subfleet);
}
} }
@@ -1,167 +0,0 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Contracts\Controller;
use App\Http\Requests\CreateTypeRatingRequest;
use App\Http\Requests\UpdateTypeRatingRequest;
use App\Repositories\SubfleetRepository;
use App\Repositories\TypeRatingRepository;
use App\Services\FleetService;
use Cache;
use Illuminate\Http\Request;
use Laracasts\Flash\Flash;
use Prettus\Repository\Criteria\RequestCriteria;
class TypeRatingController extends Controller
{
private $fleetSvc;
private $subfleetRepo;
private $typeratingRepo;
public function __construct(
FleetService $fleetSvc,
SubfleetRepository $subfleetRepo,
TypeRatingRepository $typeratingRepo
) {
$this->fleetSvc = $fleetSvc;
$this->subfleetRepo = $subfleetRepo;
$this->typeratingRepo = $typeratingRepo;
}
public function index(Request $request)
{
$this->typeratingRepo->pushCriteria(new RequestCriteria($request));
$typeratings = $this->typeratingRepo->orderby('type', 'asc')->get();
return view('admin.typeratings.index', [
'typeratings' => $typeratings,
]);
}
public function create()
{
return view('admin.typeratings.create');
}
public function store(CreateTypeRatingRequest $request)
{
$input = $request->all();
$model = $this->typeratingRepo->create($input);
Flash::success('Type Rating saved successfully.');
return redirect(route('admin.typeratings.edit', [$model->id]));
}
public function show($id)
{
$typerating = $this->typeratingRepo->findWithoutFail($id);
if (empty($typerating)) {
Flash::error('Type Rating not found');
return redirect(route('admin.typeratings.index'));
}
return view('admin.typeratings.show', [
'typerating' => $typerating,
]);
}
public function edit($id)
{
$typerating = $this->typeratingRepo->findWithoutFail($id);
if (empty($typerating)) {
Flash::error('Type Rating not found');
return redirect(route('admin.typeratings.index'));
}
$avail_subfleets = $this->getAvailSubfleets($typerating);
return view('admin.typeratings.edit', [
'typerating' => $typerating,
'avail_subfleets' => $avail_subfleets,
]);
}
public function update($id, UpdateTypeRatingRequest $request)
{
$typerating = $this->typeratingRepo->findWithoutFail($id);
if (empty($typerating)) {
Flash::error('Type Rating not found');
return redirect(route('admin.typeratings.index'));
}
$typerating = $this->typeratingRepo->update($request->all(), $id);
// Cache::forget(config('cache.keys.RANKS_PILOT_LIST.key'));
Flash::success('Type Rating updated successfully.');
return redirect(route('admin.typeratings.index'));
}
public function destroy($id)
{
$typerating = $this->typeratingRepo->findWithoutFail($id);
if (empty($typerating)) {
Flash::error('Type Rating not found');
return redirect(route('admin.typeratings.index'));
}
$this->typeratingRepo->delete($id);
Flash::success('Type Rating deleted successfully.');
return redirect(route('admin.typeratings.index'));
}
protected function getAvailSubfleets($typerating)
{
$retval = [];
$all_subfleets = $this->subfleetRepo->all();
$avail_subfleets = $all_subfleets->except($typerating->subfleets->modelKeys());
foreach ($avail_subfleets as $subfleet) {
$retval[$subfleet->id] = $subfleet->name.' (Airline: '.$subfleet->airline->code.')';
}
return $retval;
}
protected function return_subfleet_view($typerating)
{
$avail_subfleets = $this->getAvailSubfleets($typerating);
return view('admin.typeratings.subfleets', [
'typerating' => $typerating,
'avail_subfleets' => $avail_subfleets,
]);
}
public function subfleets($id, Request $request)
{
$typerating = $this->typeratingRepo->findWithoutFail($id);
if (empty($typerating)) {
Flash::error('Type Rating not found!');
return redirect(route('admin.typeratings.index'));
}
// add subfleet to type rating
if ($request->isMethod('post')) {
$subfleet = $this->subfleetRepo->find($request->input('subfleet_id'));
$this->fleetSvc->addSubfleetToTypeRating($subfleet, $typerating);
}
// remove subfleet from type rating
elseif ($request->isMethod('delete')) {
$subfleet = $this->subfleetRepo->find($request->input('subfleet_id'));
$this->fleetSvc->removeSubfleetFromTypeRating($subfleet, $typerating);
}
return $this->return_subfleet_view($typerating);
}
}
+16 -94
View File
@@ -12,7 +12,6 @@ use App\Repositories\AirlineRepository;
use App\Repositories\AirportRepository; use App\Repositories\AirportRepository;
use App\Repositories\PirepRepository; use App\Repositories\PirepRepository;
use App\Repositories\RoleRepository; use App\Repositories\RoleRepository;
use App\Repositories\TypeRatingRepository;
use App\Repositories\UserRepository; use App\Repositories\UserRepository;
use App\Services\UserService; use App\Services\UserService;
use App\Support\Timezonelist; use App\Support\Timezonelist;
@@ -31,27 +30,24 @@ class UserController extends Controller
private $airportRepo; private $airportRepo;
private $pirepRepo; private $pirepRepo;
private $roleRepo; private $roleRepo;
private $typeratingRepo;
private $userRepo; private $userRepo;
private $userSvc; private $userSvc;
/** /**
* UserController constructor. * UserController constructor.
* *
* @param AirlineRepository $airlineRepo * @param AirlineRepository $airlineRepo
* @param AirportRepository $airportRepo * @param AirportRepository $airportRepo
* @param PirepRepository $pirepRepo * @param PirepRepository $pirepRepo
* @param RoleRepository $roleRepo * @param RoleRepository $roleRepo
* @param TypeRatingRepository $typeratingRepo * @param UserRepository $userRepo
* @param UserRepository $userRepo * @param UserService $userSvc
* @param UserService $userSvc
*/ */
public function __construct( public function __construct(
AirlineRepository $airlineRepo, AirlineRepository $airlineRepo,
AirportRepository $airportRepo, AirportRepository $airportRepo,
PirepRepository $pirepRepo, PirepRepository $pirepRepo,
RoleRepository $roleRepo, RoleRepository $roleRepo,
TypeRatingRepository $typeratingRepo,
UserRepository $userRepo, UserRepository $userRepo,
UserService $userSvc UserService $userSvc
) { ) {
@@ -59,7 +55,6 @@ class UserController extends Controller
$this->airportRepo = $airportRepo; $this->airportRepo = $airportRepo;
$this->pirepRepo = $pirepRepo; $this->pirepRepo = $pirepRepo;
$this->roleRepo = $roleRepo; $this->roleRepo = $roleRepo;
$this->typeratingRepo = $typeratingRepo;
$this->userSvc = $userSvc; $this->userSvc = $userSvc;
$this->userRepo = $userRepo; $this->userRepo = $userRepo;
} }
@@ -154,7 +149,7 @@ class UserController extends Controller
public function edit($id) public function edit($id)
{ {
$user = $this->userRepo $user = $this->userRepo
->with(['awards', 'fields', 'rank', 'typeratings']) ->with(['awards', 'fields', 'rank'])
->findWithoutFail($id); ->findWithoutFail($id);
if (empty($user)) { if (empty($user)) {
@@ -174,19 +169,17 @@ class UserController extends Controller
$airlines = $this->airlineRepo->selectBoxList(); $airlines = $this->airlineRepo->selectBoxList();
$airports = $this->airportRepo->selectBoxList(false); $airports = $this->airportRepo->selectBoxList(false);
$roles = $this->roleRepo->selectBoxList(false, true); $roles = $this->roleRepo->selectBoxList(false, true);
$avail_ratings = $this->getAvailTypeRatings($user);
return view('admin.users.edit', [ return view('admin.users.edit', [
'user' => $user, 'user' => $user,
'pireps' => $pireps, 'pireps' => $pireps,
'country' => new ISO3166(), 'country' => new ISO3166(),
'countries' => $countries, 'countries' => $countries,
'timezones' => Timezonelist::toArray(), 'timezones' => Timezonelist::toArray(),
'airports' => $airports, 'airports' => $airports,
'airlines' => $airlines, 'airlines' => $airlines,
'ranks' => Rank::all()->pluck('name', 'id'), 'ranks' => Rank::all()->pluck('name', 'id'),
'roles' => $roles, 'roles' => $roles,
'avail_ratings' => $avail_ratings,
]); ]);
} }
@@ -267,7 +260,6 @@ class UserController extends Controller
$user = $this->userRepo->findWithoutFail($id); $user = $this->userRepo->findWithoutFail($id);
if (empty($user)) { if (empty($user)) {
Flash::error('User not found'); Flash::error('User not found');
return redirect(route('admin.users.index')); return redirect(route('admin.users.index'));
} }
@@ -291,7 +283,6 @@ class UserController extends Controller
$userAward = UserAward::where(['user_id' => $id, 'award_id' => $award_id]); $userAward = UserAward::where(['user_id' => $id, 'award_id' => $award_id]);
if (empty($userAward)) { if (empty($userAward)) {
Flash::error('The user award could not be found'); Flash::error('The user award could not be found');
return redirect()->back(); return redirect()->back();
} }
@@ -320,73 +311,4 @@ class UserController extends Controller
return redirect(route('admin.users.edit', [$id])); return redirect(route('admin.users.edit', [$id]));
} }
/**
* Get the type ratings that are available to the user
*
* @param $user
*
* @return array
*/
protected function getAvailTypeRatings($user)
{
$retval = [];
$all_ratings = $this->typeratingRepo->all();
$avail_ratings = $all_ratings->except($user->typeratings->modelKeys());
foreach ($avail_ratings as $tr) {
$retval[$tr->id] = $tr->name.' ('.$tr->type.')';
}
return $retval;
}
/**
* @param User $user
*
* @return mixed
*/
protected function return_typeratings_view(?User $user)
{
$user->refresh();
$avail_ratings = $this->getAvailTypeRatings($user);
return view('admin.users.type_ratings', [
'user' => $user,
'avail_ratings' => $avail_ratings,
]);
}
/**
* Operations for associating type ratings to the user
*
* @param $id
* @param Request $request
*
* @return mixed
*/
public function typeratings($id, Request $request)
{
$user = $this->userRepo->findWithoutFail($id);
if (empty($user)) {
return $this->return_typeratings_view($user);
}
if ($request->isMethod('get')) {
return $this->return_typeratings_view($user);
}
// associate user with type rating
if ($request->isMethod('post')) {
$typerating = $this->typeratingRepo->find($request->input('typerating_id'));
$this->userSvc->addUserToTypeRating($user, $typerating);
} // dissassociate user from the type rating
elseif ($request->isMethod('delete')) {
$typerating = $this->typeratingRepo->find($request->input('typerating_id'));
$this->userSvc->removeUserFromTypeRating($user, $typerating);
}
$user->save();
return $this->return_typeratings_view($user);
}
} }
+5 -5
View File
@@ -148,10 +148,10 @@ class AcarsController extends Controller
$pirep = Pirep::find($id); $pirep = Pirep::find($id);
$this->checkCancelled($pirep); $this->checkCancelled($pirep);
/*Log::debug( Log::debug(
'Posting ACARS update (user: '.Auth::user()->ident.', pirep id :'.$id.'): ', 'Posting ACARS update (user: '.Auth::user()->ident.', pirep id :'.$id.'): ',
$request->post() $request->post()
);*/ );
$count = 0; $count = 0;
$positions = $request->post('positions'); $positions = $request->post('positions');
@@ -193,9 +193,9 @@ class AcarsController extends Controller
} }
// Change the PIREP status if it's as SCHEDULED before // 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->status = PirepStatus::AIRBORNE;
}*/ }
$pirep->save(); $pirep->save();
@@ -223,7 +223,7 @@ class AcarsController extends Controller
$pirep = Pirep::find($id); $pirep = Pirep::find($id);
$this->checkCancelled($pirep); $this->checkCancelled($pirep);
// Log::debug('Posting ACARS log, PIREP: '.$id, $request->post()); Log::debug('Posting ACARS log, PIREP: '.$id, $request->post());
$count = 0; $count = 0;
$logs = $request->post('logs'); $logs = $request->post('logs');
@@ -30,9 +30,9 @@ class AirlineController extends Controller
*/ */
public function index(Request $request) public function index(Request $request)
{ {
$airlines = $this->airlineRepo->whereOrder(['active' => true], 'name')->paginate(); $airports = $this->airlineRepo->whereOrder(['active' => true], 'name')->get();
return AirlineResource::collection($airlines); return AirlineResource::collection($airports);
} }
/** /**
@@ -2,10 +2,10 @@
namespace App\Http\Controllers\Api; namespace App\Http\Controllers\Api;
use App\Console\Cron;
use App\Contracts\Controller; use App\Contracts\Controller;
use App\Exceptions\CronInvalid; use App\Exceptions\CronInvalid;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Artisan;
class MaintenanceController extends Controller class MaintenanceController extends Controller
{ {
@@ -24,12 +24,12 @@ class MaintenanceController extends Controller
throw new CronInvalid(); throw new CronInvalid();
} }
$cron = app(Cron::class); $output = '';
$run = $cron->run(); Artisan::call('schedule:run');
$output .= trim(Artisan::output());
return response()->json([ return response([
'count' => count($run), 'content' => $output,
'tasks' => $run,
]); ]);
} }
} }
+4 -12
View File
@@ -25,7 +25,6 @@ use App\Models\Pirep;
use App\Models\PirepComment; use App\Models\PirepComment;
use App\Models\PirepFare; use App\Models\PirepFare;
use App\Models\PirepFieldValue; use App\Models\PirepFieldValue;
use App\Models\User;
use App\Repositories\JournalRepository; use App\Repositories\JournalRepository;
use App\Repositories\PirepRepository; use App\Repositories\PirepRepository;
use App\Services\Finance\PirepFinanceService; use App\Services\Finance\PirepFinanceService;
@@ -236,12 +235,8 @@ class PirepController extends Controller
Log::info('PIREP Update, user '.Auth::id()); Log::info('PIREP Update, user '.Auth::id());
Log::info($request->getContent()); Log::info($request->getContent());
/** @var User $user */
$user = Auth::user(); $user = Auth::user();
/** @var Pirep $pirep */
$pirep = Pirep::find($pirep_id); $pirep = Pirep::find($pirep_id);
$this->checkCancelled($pirep); $this->checkCancelled($pirep);
$attrs = $this->parsePirep($request); $attrs = $this->parsePirep($request);
@@ -283,7 +278,6 @@ class PirepController extends Controller
{ {
Log::info('PIREP file, user '.Auth::id(), $request->post()); Log::info('PIREP file, user '.Auth::id(), $request->post());
/** @var User $user */
$user = Auth::user(); $user = Auth::user();
// Check if the status is cancelled... // Check if the status is cancelled...
@@ -334,18 +328,16 @@ class PirepController extends Controller
* *
* @throws \Prettus\Validator\Exceptions\ValidatorException * @throws \Prettus\Validator\Exceptions\ValidatorException
* *
* @return mixed * @return PirepResource
*/ */
public function cancel($pirep_id, Request $request) public function cancel($pirep_id, Request $request)
{ {
Log::info('PIREP '.$pirep_id.' Cancel, user '.Auth::id(), $request->post()); Log::info('PIREP Cancel, user '.Auth::id(), $request->post());
$pirep = Pirep::find($pirep_id); $pirep = Pirep::find($pirep_id);
if (!empty($pirep)) { $this->pirepSvc->cancel($pirep);
$this->pirepSvc->cancel($pirep);
}
return $this->message('PIREP '.$pirep_id.' cancelled'); return new PirepResource($pirep);
} }
/** /**
@@ -3,8 +3,6 @@
namespace App\Http\Controllers\Api; namespace App\Http\Controllers\Api;
use App\Contracts\Controller; use App\Contracts\Controller;
use App\Exceptions\BidNotFound;
use App\Exceptions\Unauthorized;
use App\Exceptions\UserNotFound; use App\Exceptions\UserNotFound;
use App\Http\Resources\Bid as BidResource; use App\Http\Resources\Bid as BidResource;
use App\Http\Resources\Pirep as PirepResource; use App\Http\Resources\Pirep as PirepResource;
@@ -146,32 +144,6 @@ class UserController extends Controller
return BidResource::collection($bids); 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 === null) {
throw new BidNotFound($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 * Return the fleet that this user is allowed to
* *
@@ -62,7 +62,7 @@ class RegisterController extends Controller
{ {
$airports = $this->airportRepo->selectBoxList(false, setting('pilots.home_hubs_only')); $airports = $this->airportRepo->selectBoxList(false, setting('pilots.home_hubs_only'));
$airlines = $this->airlineRepo->selectBoxList(); $airlines = $this->airlineRepo->selectBoxList();
$userFields = UserField::where(['show_on_registration' => true, 'active' => true])->get(); $userFields = UserField::where(['show_on_registration' => true])->get();
return view('auth.register', [ return view('auth.register', [
'airports' => $airports, 'airports' => $airports,
@@ -138,7 +138,7 @@ class RegisterController extends Controller
Log::info('User registered: ', $user->toArray()); Log::info('User registered: ', $user->toArray());
$userFields = UserField::where(['show_on_registration' => true, 'active' => true])->get(); $userFields = UserField::all();
foreach ($userFields as $field) { foreach ($userFields as $field) {
$field_name = 'field_'.$field->slug; $field_name = 'field_'.$field->slug;
UserFieldValue::updateOrCreate([ UserFieldValue::updateOrCreate([
@@ -35,23 +35,22 @@ class AirportController extends Controller
public function show($id, Request $request) public function show($id, Request $request)
{ {
$id = strtoupper($id); $id = strtoupper($id);
$with_flights = ['airline', 'arr_airport', 'dpt_airport'];
$airport = $this->airportRepo->with('files')->where('id', $id)->first(); $airport = $this->airportRepo->where('id', $id)->first();
if (!$airport) { if (!$airport) {
Flash::error('Airport not found!'); Flash::error('Airport not found!');
return redirect(route('frontend.dashboard.index')); return redirect(route('frontend.dashboard.index'));
} }
$inbound_flights = $this->flightRepo $inbound_flights = $this->flightRepo
->with($with_flights) ->with(['dpt_airport', 'arr_airport', 'airline'])
->findWhere([ ->findWhere([
'arr_airport_id' => $id, 'arr_airport_id' => $id,
'active' => 1, 'active' => 1,
])->all(); ])->all();
$outbound_flights = $this->flightRepo $outbound_flights = $this->flightRepo
->with($with_flights) ->with(['dpt_airport', 'arr_airport', 'airline'])
->findWhere([ ->findWhere([
'dpt_airport_id' => $id, 'dpt_airport_id' => $id,
'active' => 1, 'active' => 1,
@@ -28,15 +28,14 @@ class DashboardController extends Controller
*/ */
public function index() public function index()
{ {
//dd(config('backup'));
$last_pirep = null; $last_pirep = null;
$with_pirep = ['aircraft', 'arr_airport', 'comments', 'dpt_airport'];
/** @var \App\Models\User $user */ /** @var \App\Models\User $user */
$user = Auth::user(); $user = Auth::user();
$user->loadMissing('journal');
try { try {
$last_pirep = $this->pirepRepo->with($with_pirep)->find($user->last_pirep_id); $last_pirep = $this->pirepRepo->find($user->last_pirep_id);
} catch (\Exception $e) { } catch (\Exception $e) {
} }
@@ -41,25 +41,22 @@ class DownloadController extends Controller
$klass = new $class(); $klass = new $class();
$obj = $klass->find($id); $obj = $klass->find($id);
// Check if the object is there first $category = explode('\\', $class);
if (isset($obj)) { $category = end($category);
$category = explode('\\', $class);
$category = end($category);
if ($category == 'Aircraft' && $airlines > 1) { if ($category == 'Aircraft' && $airlines > 1) {
$group_name = $category.' > '.$obj->subfleet->airline->name.' '.$obj->icao.' '.$obj->registration; $group_name = $category.' > '.$obj->subfleet->airline->name.' '.$obj->icao.' '.$obj->registration;
} elseif ($category == 'Aircraft') { } elseif ($category == 'Aircraft') {
$group_name = $category.' > '.$obj->icao.' '.$obj->registration; $group_name = $category.' > '.$obj->icao.' '.$obj->registration;
} elseif ($category == 'Airport') { } elseif ($category == 'Airport') {
$group_name = $category.' > '.$obj->icao.' : '.$obj->name.' ('.$obj->country.')'; $group_name = $category.' > '.$obj->icao.' : '.$obj->name.' ('.$obj->country.')';
} elseif ($category == 'Subfleet' && $airlines > 1) { } elseif ($category == 'Subfleet' && $airlines > 1) {
$group_name = $category.' > '.$obj->airline->name.' '.$obj->name; $group_name = $category.' > '.$obj->airline->name.' '.$obj->name;
} else { } else {
$group_name = $category.' > '.$obj->name; $group_name = $category.' > '.$obj->name;
}
$regrouped_files[$group_name] = $files;
} }
$regrouped_files[$group_name] = $files;
} }
ksort($regrouped_files, SORT_STRING); ksort($regrouped_files, SORT_STRING);
@@ -13,7 +13,6 @@ use App\Repositories\FlightRepository;
use App\Repositories\SubfleetRepository; use App\Repositories\SubfleetRepository;
use App\Repositories\UserRepository; use App\Repositories\UserRepository;
use App\Services\GeoService; use App\Services\GeoService;
use App\Services\ModuleService;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
@@ -26,7 +25,6 @@ class FlightController extends Controller
private $airlineRepo; private $airlineRepo;
private $airportRepo; private $airportRepo;
private $flightRepo; private $flightRepo;
private $moduleSvc;
private $subfleetRepo; private $subfleetRepo;
private $geoSvc; private $geoSvc;
private $userRepo; private $userRepo;
@@ -36,7 +34,6 @@ class FlightController extends Controller
* @param AirportRepository $airportRepo * @param AirportRepository $airportRepo
* @param FlightRepository $flightRepo * @param FlightRepository $flightRepo
* @param GeoService $geoSvc * @param GeoService $geoSvc
* @param ModuleService $moduleSvc
* @param SubfleetRepository $subfleetRepo * @param SubfleetRepository $subfleetRepo
* @param UserRepository $userRepo * @param UserRepository $userRepo
*/ */
@@ -45,7 +42,6 @@ class FlightController extends Controller
AirportRepository $airportRepo, AirportRepository $airportRepo,
FlightRepository $flightRepo, FlightRepository $flightRepo,
GeoService $geoSvc, GeoService $geoSvc,
ModuleService $moduleSvc,
SubfleetRepository $subfleetRepo, SubfleetRepository $subfleetRepo,
UserRepository $userRepo UserRepository $userRepo
) { ) {
@@ -53,7 +49,6 @@ class FlightController extends Controller
$this->airportRepo = $airportRepo; $this->airportRepo = $airportRepo;
$this->flightRepo = $flightRepo; $this->flightRepo = $flightRepo;
$this->geoSvc = $geoSvc; $this->geoSvc = $geoSvc;
$this->moduleSvc = $moduleSvc;
$this->subfleetRepo = $subfleetRepo; $this->subfleetRepo = $subfleetRepo;
$this->userRepo = $userRepo; $this->userRepo = $userRepo;
} }
@@ -88,7 +83,6 @@ class FlightController extends Controller
/** @var \App\Models\User $user */ /** @var \App\Models\User $user */
$user = Auth::user(); $user = Auth::user();
$user->loadMissing('current_airport');
if (setting('pilots.restrict_to_company')) { if (setting('pilots.restrict_to_company')) {
$where['airline_id'] = $user->airline_id; $where['airline_id'] = $user->airline_id;
@@ -114,12 +108,7 @@ class FlightController extends Controller
// Get only used Flight Types for the search form // Get only used Flight Types for the search form
// And filter according to settings // And filter according to settings
$usedtypes = Flight::select('flight_type') $usedtypes = Flight::select('flight_type')->where($where)->groupby('flight_type')->orderby('flight_type', 'asc')->get();
->where($where)
->groupby('flight_type')
->orderby('flight_type')
->get();
// Build collection with type codes and labels // Build collection with type codes and labels
$flight_types = collect('', ''); $flight_types = collect('', '');
foreach ($usedtypes as $ftype) { foreach ($usedtypes as $ftype) {
@@ -128,28 +117,18 @@ class FlightController extends Controller
$flights = $this->flightRepo->searchCriteria($request) $flights = $this->flightRepo->searchCriteria($request)
->with([ ->with([
'airline',
'alt_airport',
'arr_airport',
'dpt_airport', 'dpt_airport',
'subfleets.airline', 'arr_airport',
'airline',
'simbrief' => function ($query) use ($user) { 'simbrief' => function ($query) use ($user) {
$query->where('user_id', $user->id); $query->where('user_id', $user->id);
}, ]) }, ])
->orderBy('flight_number') ->orderBy('flight_number', 'asc')
->orderBy('route_leg') ->orderBy('route_leg', 'asc')
->paginate(); ->paginate();
$saved_flights = []; $saved_flights = Bid::where('user_id', Auth::id())
$bids = Bid::where('user_id', Auth::id())->get(); ->pluck('flight_id')->toArray();
foreach ($bids as $bid) {
if (!$bid->flight) {
$bid->delete();
continue;
}
$saved_flights[$bid->flight_id] = $bid->id;
}
return view('flights.index', [ return view('flights.index', [
'user' => $user, 'user' => $user,
@@ -166,7 +145,6 @@ class FlightController extends Controller
'subfleet_id' => $request->input('subfleet_id'), 'subfleet_id' => $request->input('subfleet_id'),
'simbrief' => !empty(setting('simbrief.api_key')), 'simbrief' => !empty(setting('simbrief.api_key')),
'simbrief_bids' => setting('simbrief.only_bids'), 'simbrief_bids' => setting('simbrief.only_bids'),
'acars_plugin' => $this->moduleSvc->isModuleActive('VMSAcars'),
]); ]);
} }
@@ -193,7 +171,7 @@ class FlightController extends Controller
} }
$flights->add($bid->flight); $flights->add($bid->flight);
$saved_flights[$bid->flight_id] = $bid->id; $saved_flights[] = $bid->flight->id;
} }
return view('flights.bids', [ return view('flights.bids', [
@@ -205,7 +183,6 @@ class FlightController extends Controller
'subfleets' => $this->subfleetRepo->selectBoxList(true), 'subfleets' => $this->subfleetRepo->selectBoxList(true),
'simbrief' => !empty(setting('simbrief.api_key')), 'simbrief' => !empty(setting('simbrief.api_key')),
'simbrief_bids' => setting('simbrief.only_bids'), 'simbrief_bids' => setting('simbrief.only_bids'),
'acars_plugin' => $this->moduleSvc->isModuleActive('VMSAcars'),
]); ]);
} }
@@ -218,19 +195,7 @@ class FlightController extends Controller
*/ */
public function show($id) public function show($id)
{ {
$user_id = Auth::id(); $flight = $this->flightRepo->find($id);
$with_flight = [
'airline',
'alt_airport',
'arr_airport',
'dpt_airport',
'subfleets.airline',
'simbrief' => function ($query) use ($user_id) {
$query->where('user_id', $user_id);
},
];
$flight = $this->flightRepo->with($with_flight)->find($id);
if (empty($flight)) { if (empty($flight)) {
Flash::error('Flight not found!'); Flash::error('Flight not found!');
return redirect(route('frontend.dashboard.index')); return redirect(route('frontend.dashboard.index'));
@@ -238,14 +203,9 @@ class FlightController extends Controller
$map_features = $this->geoSvc->flightGeoJson($flight); $map_features = $this->geoSvc->flightGeoJson($flight);
// See if the user has a bid for this flight
$bid = Bid::where(['user_id' => $user_id, 'flight_id' => $flight->id])->first();
return view('flights.show', [ return view('flights.show', [
'flight' => $flight, 'flight' => $flight,
'map_features' => $map_features, 'map_features' => $map_features,
'bid' => $bid,
'acars_plugin' => $this->moduleSvc->isModuleActive('VMSAcars'),
]); ]);
} }
} }
@@ -16,7 +16,7 @@ class HomeController extends Controller
public function index() public function index()
{ {
try { try {
$users = User::with('home_airport')->where('state', '!=', UserState::DELETED)->orderBy('created_at', 'desc')->take(4)->get(); $users = User::where('state', '!=', UserState::DELETED)->orderBy('created_at', 'desc')->take(4)->get();
} catch (\PDOException $e) { } catch (\PDOException $e) {
Log::emergency($e); Log::emergency($e);
return view('system/errors/database_error', [ return view('system/errors/database_error', [
@@ -91,12 +91,8 @@ class PirepController extends Controller
*/ */
public function aircraftList($add_blank = false) public function aircraftList($add_blank = false)
{ {
$user = Auth::user();
$user_loc = filled($user->curr_airport_id) ? $user->curr_airport_id : $user->home_airport_id;
$location_check = setting('pireps.only_aircraft_at_dpt_airport', false);
$aircraft = []; $aircraft = [];
$subfleets = $this->userSvc->getAllowableSubfleets($user); $subfleets = $this->userSvc->getAllowableSubfleets(Auth::user());
if ($add_blank) { if ($add_blank) {
$aircraft[''] = ''; $aircraft[''] = '';
@@ -104,9 +100,7 @@ class PirepController extends Controller
foreach ($subfleets as $subfleet) { foreach ($subfleets as $subfleet) {
$tmp = []; $tmp = [];
foreach ($subfleet->aircraft->when($location_check, function ($query) use ($user_loc) { foreach ($subfleet->aircraft as $ac) {
return $query->where('airport_id', $user_loc);
}) as $ac) {
$tmp[$ac->id] = $ac['name'].' - '.$ac['registration']; $tmp[$ac->id] = $ac['name'].' - '.$ac['registration'];
} }
@@ -188,7 +182,7 @@ class PirepController extends Controller
$where = [['user_id', $user->id]]; $where = [['user_id', $user->id]];
$where[] = ['state', '<>', PirepState::CANCELLED]; $where[] = ['state', '<>', PirepState::CANCELLED];
$with = ['aircraft', 'airline', 'arr_airport', 'comments', 'dpt_airport']; $with = ['airline', 'aircraft', 'dpt_airport', 'arr_airport', 'fares', 'comments'];
$this->pirepRepo->with($with) $this->pirepRepo->with($with)
->pushCriteria(new WhereCriteria($request, $where)); ->pushCriteria(new WhereCriteria($request, $where));
@@ -207,20 +201,7 @@ class PirepController extends Controller
*/ */
public function show($id) public function show($id)
{ {
$with = [ $pirep = $this->pirepRepo->with(['simbrief'])->find($id);
'acars_logs',
'aircraft.airline',
'airline.journal',
'arr_airport',
'comments',
'dpt_airport',
'fares.fare',
'transactions',
'simbrief',
'user.rank',
];
$pirep = $this->pirepRepo->with($with)->find($id);
if (empty($pirep)) { if (empty($pirep)) {
Flash::error('Pirep not found'); Flash::error('Pirep not found');
return redirect(route('frontend.pirep.index')); return redirect(route('frontend.pirep.index'));
@@ -80,19 +80,22 @@ class ProfileController extends Controller
public function show($id) public function show($id)
{ {
/** @var \App\Models\User $user */ /** @var \App\Models\User $user */
$with = ['airline', 'awards', 'current_airport', 'fields.field', 'home_airport', 'last_pirep', 'rank', 'typeratings']; $user = User::with(['awards', 'fields', 'fields.field'])
$user = User::with($with)->where('id', $id)->first(); ->where('id', $id)
->first();
if (empty($user)) { if (empty($user)) {
Flash::error('User not found!'); Flash::error('User not found!');
return redirect(route('frontend.dashboard.index')); return redirect(route('frontend.dashboard.index'));
} }
$airports = $this->airportRepo->all();
$userFields = $this->userRepo->getUserFields($user, true); $userFields = $this->userRepo->getUserFields($user, true);
return view('profile.index', [ return view('profile.index', [
'user' => $user, 'user' => $user,
'userFields' => $userFields, 'userFields' => $userFields,
'airports' => $airports,
'acars' => $this->acarsEnabled(), 'acars' => $this->acarsEnabled(),
]); ]);
} }
@@ -109,7 +112,9 @@ class ProfileController extends Controller
public function edit(Request $request) public function edit(Request $request)
{ {
/** @var \App\Models\User $user */ /** @var \App\Models\User $user */
$user = User::with('fields.field')->where('id', Auth::id())->first(); $user = User::with(['fields', 'fields.field'])
->where('id', Auth::user()->id)
->first();
if (empty($user)) { if (empty($user)) {
Flash::error('User not found!'); Flash::error('User not found!');
@@ -118,7 +123,7 @@ class ProfileController extends Controller
$airlines = $this->airlineRepo->selectBoxList(); $airlines = $this->airlineRepo->selectBoxList();
$airports = $this->airportRepo->selectBoxList(false, setting('pilots.home_hubs_only')); $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', [ return view('profile.edit', [
'user' => $user, 'user' => $user,
@@ -4,7 +4,6 @@ namespace App\Http\Controllers\Frontend;
use App\Exceptions\AssetNotFound; use App\Exceptions\AssetNotFound;
use App\Models\Aircraft; use App\Models\Aircraft;
use App\Models\Bid;
use App\Models\Enums\AircraftState; use App\Models\Enums\AircraftState;
use App\Models\Enums\AircraftStatus; use App\Models\Enums\AircraftStatus;
use App\Models\Enums\FareType; use App\Models\Enums\FareType;
@@ -15,7 +14,6 @@ use App\Models\SimBrief;
use App\Models\User; use App\Models\User;
use App\Repositories\FlightRepository; use App\Repositories\FlightRepository;
use App\Services\FareService; use App\Services\FareService;
use App\Services\ModuleService;
use App\Services\SimBriefService; use App\Services\SimBriefService;
use App\Services\UserService; use App\Services\UserService;
use Exception; use Exception;
@@ -26,20 +24,17 @@ class SimBriefController
{ {
private $fareSvc; private $fareSvc;
private $flightRepo; private $flightRepo;
private $moduleSvc;
private $simBriefSvc; private $simBriefSvc;
private $userSvc; private $userSvc;
public function __construct( public function __construct(
FareService $fareSvc, FareService $fareSvc,
FlightRepository $flightRepo, FlightRepository $flightRepo,
ModuleService $moduleSvc,
SimBriefService $simBriefSvc, SimBriefService $simBriefSvc,
UserService $userSvc UserService $userSvc
) { ) {
$this->fareSvc = $fareSvc; $this->fareSvc = $fareSvc;
$this->flightRepo = $flightRepo; $this->flightRepo = $flightRepo;
$this->moduleSvc = $moduleSvc;
$this->simBriefSvc = $simBriefSvc; $this->simBriefSvc = $simBriefSvc;
$this->userSvc = $userSvc; $this->userSvc = $userSvc;
} }
@@ -62,7 +57,7 @@ class SimBriefController
$aircraft_id = $request->input('aircraft_id'); $aircraft_id = $request->input('aircraft_id');
/** @var Flight $flight */ /** @var Flight $flight */
$flight = $this->flightRepo->with(['airline', 'arr_airport', 'dpt_airport', 'fares', 'subfleets'])->find($flight_id); $flight = $this->flightRepo->with(['fares', 'subfleets'])->find($flight_id);
if (!$flight) { if (!$flight) {
flash()->error('Unknown flight'); flash()->error('Unknown flight');
@@ -80,39 +75,45 @@ class SimBriefController
// No aircraft selected, show selection form // No aircraft selected, show selection form
if (!$aircraft_id) { if (!$aircraft_id) {
// If no subfleets defined for flight get them from user
// Get user's allowed subfleets and intersect it with flight subfleets if ($flight->subfleets->count() > 0) {
// so we will have a proper list which the user is allowed to fly $subfleets = $flight->subfleets;
$user_subfleets = $this->userSvc->getAllowableSubfleets($user)->pluck('id')->toArray(); } else {
$flight_subfleets = $flight->subfleets->pluck('id')->toArray(); $subfleets = $this->userSvc->getAllowableSubfleets($user);
$subfleet_ids = filled($flight_subfleets) ? array_intersect($user_subfleets, $flight_subfleets) : $user_subfleets;
// Prepare variables for single aircraft query
$where = [];
$where['state'] = AircraftState::PARKED;
$where['status'] = AircraftStatus::ACTIVE;
if (setting('pireps.only_aircraft_at_dpt_airport')) {
$where['airport_id'] = $flight->dpt_airport_id;
} }
$withCount = ['simbriefs' => function ($query) { // Build an array of subfleet id's from the subfleets collection
$query->whereNull('pirep_id'); $sf_ids = $subfleets->map(function ($subfleets) {
}]; return collect($subfleets->toArray())
->only(['id'])
->all();
});
// Build proper aircraft collection considering all possible settings // Now we can build a proper aircrafts collection
// Flight subfleets, user subfleet restrictions, pirep restrictions, simbrief blocking etc // Contents will be either members of flight->subfleets
$aircraft = Aircraft::withCount($withCount)->where($where) // or members of user's allowable subfleets
->when(setting('simbrief.block_aircraft'), function ($query) { $aircrafts = Aircraft::whereIn('subfleet_id', $sf_ids)
return $query->having('simbriefs_count', 0); ->where('state', AircraftState::PARKED)
})->whereIn('subfleet_id', $subfleet_ids) ->where('status', AircraftStatus::ACTIVE)
->orderby('icao')->orderby('registration') ->orderby('icao')
->get(); ->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', [ return view('flights.simbrief_aircraft', [
'flight' => $flight, 'flight' => $flight,
'aircrafts' => $aircraft, 'aircrafts' => $aircrafts,
'subfleets' => $subfleets,
]); ]);
} }
@@ -129,7 +130,7 @@ class SimBriefController
// SimBrief profile does not exists and everything else is ok // SimBrief profile does not exists and everything else is ok
// Select aircraft which will be used for calculations and details // Select aircraft which will be used for calculations and details
/** @var Aircraft $aircraft */ /** @var Aircraft $aircraft */
$aircraft = Aircraft::with(['airline'])->where('id', $aircraft_id)->first(); $aircraft = Aircraft::where('id', $aircraft_id)->first();
// Figure out the proper fares to use for this flight/aircraft // Figure out the proper fares to use for this flight/aircraft
$all_fares = $this->fareSvc->getFareWithOverrides($aircraft->subfleet->fares, $flight->fares); $all_fares = $this->fareSvc->getFareWithOverrides($aircraft->subfleet->fares, $flight->fares);
@@ -224,7 +225,7 @@ class SimBriefController
// Show the main simbrief form // Show the main simbrief form
return view('flights.simbrief_form', [ return view('flights.simbrief_form', [
'user' => $user, 'user' => Auth::user(),
'flight' => $flight, 'flight' => $flight,
'aircraft' => $aircraft, 'aircraft' => $aircraft,
'pax_weight' => $pax_weight, 'pax_weight' => $pax_weight,
@@ -252,11 +253,7 @@ class SimBriefController
*/ */
public function briefing($id) public function briefing($id)
{ {
/** @var User $user */ $simbrief = SimBrief::find($id);
$user = Auth::user();
/** @var SimBrief $simbrief */
$simbrief = SimBrief::with(['flight.airline', 'pirep.airline'])->find($id);
if (!$simbrief) { if (!$simbrief) {
flash()->error('SimBrief briefing not found'); flash()->error('SimBrief briefing not found');
return redirect(route('frontend.flights.index')); return redirect(route('frontend.flights.index'));
@@ -269,18 +266,11 @@ class SimBriefController
$equipment = substr($str, $wc + 1, $tr - 2); $equipment = substr($str, $wc + 1, $tr - 2);
$transponder = substr($str, $tr + 1); $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', [ return view('flights.simbrief_briefing', [
'user' => $user, 'simbrief' => $simbrief,
'simbrief' => $simbrief, 'wakecat' => $wakecat,
'wakecat' => $wakecat, 'equipment' => $equipment,
'equipment' => $equipment, 'transponder' => $transponder,
'transponder' => $transponder,
'bid' => $bid,
'flight' => $simbrief->flight,
'acars_plugin' => $this->moduleSvc->isModuleActive('VMSAcars'),
]); ]);
} }
@@ -30,9 +30,6 @@ class UserController extends Controller
*/ */
public function index(Request $request) public function index(Request $request)
{ {
$with = ['airline', 'current_airport', 'fields.field', 'home_airport', 'rank'];
$with_count = ['awards'];
$where = []; $where = [];
if (setting('pilots.hide_inactive')) { if (setting('pilots.hide_inactive')) {
@@ -46,8 +43,7 @@ class UserController extends Controller
} }
$users = $this->userRepo $users = $this->userRepo
->withCount($with_count) ->with(['airline', 'current_airport'])
->with($with)
->orderBy('pilot_id', 'asc') ->orderBy('pilot_id', 'asc')
->paginate(); ->paginate();
@@ -1,19 +0,0 @@
<?php
namespace App\Http\Requests;
use App\Contracts\FormRequest;
use App\Models\Typerating;
class CreateTypeRatingRequest extends FormRequest
{
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules(): array
{
return Typerating::$rules;
}
}
@@ -1,19 +0,0 @@
<?php
namespace App\Http\Requests;
use App\Contracts\FormRequest;
use App\Models\Typerating;
class UpdateTypeRatingRequest extends FormRequest
{
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules(): array
{
return Typerating::$rules;
}
}
-10
View File
@@ -4,16 +4,6 @@ namespace App\Http\Resources;
use App\Contracts\Resource; use App\Contracts\Resource;
/**
* @mixin \App\Models\Aircraft
*/
class Aircraft extends Resource class Aircraft extends Resource
{ {
public function toArray($request)
{
$res = parent::toArray($request);
$res['ident'] = $this->ident;
return $res;
}
} }
+1 -1
View File
@@ -60,7 +60,7 @@ class AwardHandler extends Listener
*/ */
public function checkForAwards($user) public function checkForAwards($user)
{ {
$awards = Award::where('active', 1)->get(); $awards = Award::all();
foreach ($awards as $award) { foreach ($awards as $award) {
$klass = $award->getReference($award, $user); $klass = $award->getReference($award, $user);
if ($klass) { if ($klass) {
+1 -3
View File
@@ -4,8 +4,6 @@ namespace App\Listeners;
use App\Contracts\Listener; use App\Contracts\Listener;
use App\Events\Expenses; use App\Events\Expenses;
use App\Models\Enums\ExpenseType;
use App\Models\Expense;
class ExpenseListener extends Listener class ExpenseListener extends Listener
{ {
@@ -25,7 +23,7 @@ class ExpenseListener extends Listener
// The transaction group is how it will show as a line item // The transaction group is how it will show as a line item
/*$expenses[] = new Expense([ /*$expenses[] = new Expense([
'type' => ExpenseType::FLIGHT, 'type' => ExpenseType::FLIGHT,
'amount' => 150, # $150 'amount' => 15000, # $150
'transaction_group' => '', 'transaction_group' => '',
'charge_to_user' => true|false 'charge_to_user' => true|false
]);*/ ]);*/
-39
View File
@@ -1,39 +0,0 @@
<?php
namespace App\Listeners;
use App\Contracts\Listener;
use App\Events\Fares;
use App\Models\Enums\FareType;
use App\Models\Fare;
class FareListener extends Listener
{
/**
* Return a list of additional fares/income items
*
* @param Fares $event
*
* @return mixed
*/
public function handle(Fares $event)
{
$fares = [];
// This is an example of a fare to return
// You have the pirep on $event->pirep and any associated data
// Cost may be skipped at all if not needed
// Notes will be used as transaction group and it is how it will show as a line item
/*
$fares[] = new Fare([
'name' => 'Duty Free Sales',
'type' => FareType::PASSENGER,
'price' => 985,
'cost' => 126,
'notes' => 'InFlight Sales',
]);
*/
return $fares;
}
}
-37
View File
@@ -7,13 +7,11 @@ use App\Models\Enums\AircraftStatus;
use App\Models\Traits\ExpensableTrait; use App\Models\Traits\ExpensableTrait;
use App\Models\Traits\FilesTrait; use App\Models\Traits\FilesTrait;
use Carbon\Carbon; use Carbon\Carbon;
use Znck\Eloquent\Traits\BelongsToThrough;
/** /**
* @property int id * @property int id
* @property mixed subfleet_id * @property mixed subfleet_id
* @property string airport_id The apt where the aircraft is * @property string airport_id The apt where the aircraft is
* @property string hub_id The apt where the aircraft is based
* @property string ident * @property string ident
* @property string name * @property string name
* @property string icao * @property string icao
@@ -23,7 +21,6 @@ use Znck\Eloquent\Traits\BelongsToThrough;
* @property float zfw * @property float zfw
* @property string hex_code * @property string hex_code
* @property Airport airport * @property Airport airport
* @property Airport hub
* @property Subfleet subfleet * @property Subfleet subfleet
* @property int status * @property int status
* @property int state * @property int state
@@ -34,14 +31,12 @@ class Aircraft extends Model
{ {
use ExpensableTrait; use ExpensableTrait;
use FilesTrait; use FilesTrait;
use BelongsToThrough;
public $table = 'aircraft'; public $table = 'aircraft';
protected $fillable = [ protected $fillable = [
'subfleet_id', 'subfleet_id',
'airport_id', 'airport_id',
'hub_id',
'iata', 'iata',
'icao', 'icao',
'name', 'name',
@@ -105,46 +100,14 @@ class Aircraft extends Model
$this->attributes['icao'] = strtoupper($icao); $this->attributes['icao'] = strtoupper($icao);
} }
/**
* Return the landing time in carbon format if provided
*
* @return Carbon|null
*/
public function getLandingTimeAttribute()
{
if (array_key_exists('landing_time', $this->attributes) && filled($this->attributes['landing_time'])) {
return new Carbon($this->attributes['landing_time']);
}
}
/** /**
* foreign keys * foreign keys
*/ */
public function airline()
{
return $this->belongsToThrough(Airline::class, Subfleet::class);
}
public function airport() public function airport()
{ {
return $this->belongsTo(Airport::class, 'airport_id'); return $this->belongsTo(Airport::class, 'airport_id');
} }
public function hub()
{
return $this->hasOne(Airport::class, 'id', 'hub_id');
}
public function pireps()
{
return $this->hasMany(Pirep::class, 'aircraft_id');
}
public function simbriefs()
{
return $this->hasMany(SimBrief::class, 'aircraft_id');
}
public function subfleet() public function subfleet()
{ {
return $this->belongsTo(Subfleet::class, 'subfleet_id'); return $this->belongsTo(Subfleet::class, 'subfleet_id');
-5
View File
@@ -103,11 +103,6 @@ class Airline extends Model
return $this->hasMany(Subfleet::class, 'airline_id'); return $this->hasMany(Subfleet::class, 'airline_id');
} }
public function aircraft()
{
return $this->hasManyThrough(Aircraft::class, Subfleet::class);
}
public function flights() public function flights()
{ {
return $this->belongsTo(Flight::class, 'airline_id'); return $this->belongsTo(Flight::class, 'airline_id');
-2
View File
@@ -21,7 +21,6 @@ class Award extends Model
'image_url', 'image_url',
'ref_model', 'ref_model',
'ref_model_params', 'ref_model_params',
'active',
]; ];
public static $rules = [ public static $rules = [
@@ -30,7 +29,6 @@ class Award extends Model
'image_url' => 'nullable', 'image_url' => 'nullable',
'ref_model' => 'required', 'ref_model' => 'required',
'ref_model_params' => 'nullable', 'ref_model_params' => 'nullable',
'active' => 'nullable',
]; ];
/** /**
+1 -3
View File
@@ -6,12 +6,10 @@ use App\Contracts\Model;
use Carbon\Carbon; use Carbon\Carbon;
/** /**
* @property int user_id * @property string user_id
* @property string flight_id * @property string flight_id
* @property Carbon created_at * @property Carbon created_at
* @property Carbon updated_at * @property Carbon updated_at
* @property Flight flight
* @property User user
*/ */
class Bid extends Model class Bid extends Model
{ {
-2
View File
@@ -7,7 +7,6 @@ use App\Contracts\Enum;
class AircraftStatus extends Enum class AircraftStatus extends Enum
{ {
public const ACTIVE = 'A'; public const ACTIVE = 'A';
public const MAINTENANCE = 'M';
public const STORED = 'S'; public const STORED = 'S';
public const RETIRED = 'R'; public const RETIRED = 'R';
public const SCRAPPED = 'C'; public const SCRAPPED = 'C';
@@ -15,7 +14,6 @@ class AircraftStatus extends Enum
public static $labels = [ public static $labels = [
self::ACTIVE => 'aircraft.status.active', self::ACTIVE => 'aircraft.status.active',
self::MAINTENANCE => 'aircraft.status.maintenance',
self::STORED => 'aircraft.status.stored', self::STORED => 'aircraft.status.stored',
self::RETIRED => 'aircraft.status.retired', self::RETIRED => 'aircraft.status.retired',
self::SCRAPPED => 'aircraft.status.scrapped', self::SCRAPPED => 'aircraft.status.scrapped',
+3 -2
View File
@@ -4,6 +4,9 @@ namespace App\Models\Enums;
use App\Contracts\Enum; use App\Contracts\Enum;
/**
* Class PirepState
*/
class PirepState extends Enum class PirepState extends Enum
{ {
public const IN_PROGRESS = 0; // flight is ongoing public const IN_PROGRESS = 0; // flight is ongoing
@@ -13,7 +16,6 @@ class PirepState extends Enum
public const DELETED = 4; public const DELETED = 4;
public const DRAFT = 5; public const DRAFT = 5;
public const REJECTED = 6; public const REJECTED = 6;
public const PAUSED = 7;
protected static $labels = [ protected static $labels = [
self::IN_PROGRESS => 'pireps.state.in_progress', self::IN_PROGRESS => 'pireps.state.in_progress',
@@ -23,6 +25,5 @@ class PirepState extends Enum
self::DELETED => 'pireps.state.deleted', self::DELETED => 'pireps.state.deleted',
self::DRAFT => 'pireps.state.draft', self::DRAFT => 'pireps.state.draft',
self::REJECTED => 'pireps.state.rejected', self::REJECTED => 'pireps.state.rejected',
self::PAUSED => 'pireps.state.paused',
]; ];
} }
-2
View File
@@ -34,7 +34,6 @@ class PirepStatus extends Enum
public const ARRIVED = 'ONB'; // On block public const ARRIVED = 'ONB'; // On block
public const CANCELLED = 'DX'; public const CANCELLED = 'DX';
public const EMERG_DESCENT = 'EMG'; public const EMERG_DESCENT = 'EMG';
public const PAUSED = 'PSD';
protected static $labels = [ protected static $labels = [
self::INITIATED => 'pireps.status.initialized', self::INITIATED => 'pireps.status.initialized',
@@ -60,6 +59,5 @@ class PirepStatus extends Enum
self::ARRIVED => 'pireps.status.arrived', self::ARRIVED => 'pireps.status.arrived',
self::CANCELLED => 'pireps.status.cancelled', self::CANCELLED => 'pireps.status.cancelled',
self::EMERG_DESCENT => 'pireps.status.emerg_decent', self::EMERG_DESCENT => 'pireps.status.emerg_decent',
self::PAUSED => 'pireps.status.paused',
]; ];
} }
+4 -5
View File
@@ -24,7 +24,6 @@ use Illuminate\Support\Collection;
* @property Collection subfleets * @property Collection subfleets
* @property int days * @property int days
* @property int distance * @property int distance
* @property int planned_distance
* @property int flight_time * @property int flight_time
* @property string route * @property string route
* @property string dpt_time * @property string dpt_time
@@ -137,19 +136,19 @@ class Flight extends Model
} }
/** /**
* Get the flight ident, e.,g JBU1900/C.nn/L.yy * Get the flight ident, e.,g JBU1900
*/ */
public function getIdentAttribute(): string public function getIdentAttribute(): string
{ {
$flight_id = optional($this->airline)->code; $flight_id = $this->airline->code;
$flight_id .= $this->flight_number; $flight_id .= $this->flight_number;
if (filled($this->route_code)) { if (filled($this->route_code)) {
$flight_id .= '/C.'.$this->route_code; $flight_id .= '-'.$this->route_code;
} }
if (filled($this->route_leg)) { if (filled($this->route_leg)) {
$flight_id .= '/L.'.$this->route_leg; $flight_id .= '-'.$this->route_leg;
} }
return $flight_id; return $flight_id;
+18 -16
View File
@@ -195,39 +195,41 @@ class Pirep extends Model
/** /**
* Create a new PIREP from a SimBrief instance * Create a new PIREP from a SimBrief instance
* *
* @param \App\Models\SimBrief $simbrief * @param \App\Models\SimBrief $simBrief
* *
* @return \App\Models\Pirep * @return \App\Models\Pirep
*/ */
public static function fromSimBrief(SimBrief $simbrief): self public static function fromSimBrief(SimBrief $simBrief): self
{ {
return new self([ return new self([
'flight_id' => $simbrief->flight->id, 'flight_id' => $simBrief->flight->id,
'airline_id' => $simbrief->flight->airline_id, 'airline_id' => $simBrief->flight->airline_id,
'flight_number' => $simbrief->flight->flight_number, 'flight_number' => $simBrief->flight->flight_number,
'route_code' => $simbrief->flight->route_code, 'route_code' => $simBrief->flight->route_code,
'route_leg' => $simbrief->flight->route_leg, 'route_leg' => $simBrief->flight->route_leg,
'dpt_airport_id' => $simbrief->flight->dpt_airport_id, 'dpt_airport_id' => $simBrief->flight->dpt_airport_id,
'arr_airport_id' => $simbrief->flight->arr_airport_id, 'arr_airport_id' => $simBrief->flight->arr_airport_id,
'route' => $simbrief->xml->getRouteString(), 'route' => $simBrief->xml->getRouteString(),
'level' => $simbrief->xml->getFlightLevel(), 'level' => $simBrief->xml->getFlightLevel(),
]); ]);
} }
/** /**
* Get the flight ident, e.,g JBU1900/C.nn/L.yy * Get the flight ident, e.,g JBU1900
*
* @return string
*/ */
public function getIdentAttribute(): string public function getIdentAttribute(): string
{ {
$flight_id = optional($this->airline)->code; //$flight_id = $this->airline->code;
$flight_id .= $this->flight_number; $flight_id = $this->flight_number;
if (filled($this->route_code)) { if (filled($this->route_code)) {
$flight_id .= '/C.'.$this->route_code; $flight_id .= '/C'.$this->route_code;
} }
if (filled($this->route_leg)) { if (filled($this->route_leg)) {
$flight_id .= '/L.'.$this->route_leg; $flight_id .= '/L'.$this->route_leg;
} }
return $flight_id; return $flight_id;
+6 -9
View File
@@ -41,10 +41,6 @@ class SimBrief extends Model
'updated_at', 'updated_at',
]; ];
protected $casts = [
'user_id' => 'integer',
];
/** @var \App\Models\SimBriefXML Store a cached version of the XML object */ /** @var \App\Models\SimBriefXML Store a cached version of the XML object */
private $xml_instance; private $xml_instance;
@@ -96,12 +92,13 @@ class SimBrief extends Model
public function flight() 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() if (!empty($this->attributes['pirep_id'])) {
{ return $this->belongsTo(Pirep::class, 'pirep_id');
return $this->belongsTo(Pirep::class, 'pirep_id'); }
} }
public function user() public function user()
-5
View File
@@ -107,9 +107,4 @@ class Subfleet extends Model
return $this->belongsToMany(Rank::class, 'subfleet_rank') return $this->belongsToMany(Rank::class, 'subfleet_rank')
->withPivot('acars_pay', 'manual_pay'); ->withPivot('acars_pay', 'manual_pay');
} }
public function typeratings()
{
return $this->belongsToMany(Typerating::class, 'typerating_subfleet', 'subfleet_id', 'typerating_id');
}
} }
-37
View File
@@ -1,37 +0,0 @@
<?php
namespace App\Models;
use App\Contracts\Model;
class Typerating extends Model
{
public $table = 'typeratings';
protected $fillable = [
'name',
'type',
'description',
'image_url',
'active',
];
// Validation
public static $rules = [
'name' => 'required',
'type' => 'required',
'description' => 'nullable',
'image_url' => 'nullable',
];
// Relationships
public function subfleets()
{
return $this->belongsToMany(Subfleet::class, 'typerating_subfleet', 'typerating_id', 'subfleet_id');
}
public function users()
{
return $this->belongsToMany(User::class, 'typerating_user', 'typerating_id', 'user_id');
}
}
+4 -22
View File
@@ -7,7 +7,6 @@ use App\Models\Traits\JournalTrait;
use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable; use Illuminate\Notifications\Notifiable;
use Laratrust\Traits\LaratrustUserTrait; use Laratrust\Traits\LaratrustUserTrait;
use Staudenmeir\EloquentHasManyDeep\HasRelationships;
/** /**
* @property int id * @property int id
@@ -43,7 +42,6 @@ use Staudenmeir\EloquentHasManyDeep\HasRelationships;
* @property UserFieldValue[] fields * @property UserFieldValue[] fields
* @property Role[] roles * @property Role[] roles
* @property Subfleet[] subfleets * @property Subfleet[] subfleets
* @property TypeRating[] typeratings
* *
* @mixin \Illuminate\Database\Eloquent\Builder * @mixin \Illuminate\Database\Eloquent\Builder
* @mixin \Illuminate\Notifications\Notifiable * @mixin \Illuminate\Notifications\Notifiable
@@ -54,7 +52,6 @@ class User extends Authenticatable
use JournalTrait; use JournalTrait;
use LaratrustUserTrait; use LaratrustUserTrait;
use Notifiable; use Notifiable;
use HasRelationships;
public $table = 'users'; public $table = 'users';
@@ -88,7 +85,6 @@ class User extends Authenticatable
'toc_accepted', 'toc_accepted',
'opt_in', 'opt_in',
'last_ip', 'last_ip',
'notes',
'created_at', 'created_at',
'updated_at', 'updated_at',
]; ];
@@ -98,14 +94,10 @@ class User extends Authenticatable
*/ */
protected $hidden = [ protected $hidden = [
'api_key', 'api_key',
'email',
'name',
'discord_id', 'discord_id',
'discord_private_channel_id',
'password', 'password',
'last_ip', 'last_ip',
'remember_token', 'remember_token',
'notes',
]; ];
protected $casts = [ protected $casts = [
@@ -133,9 +125,8 @@ class User extends Authenticatable
public function getIdentAttribute(): string public function getIdentAttribute(): string
{ {
$length = setting('pilots.id_length'); $length = setting('pilots.id_length');
$ident_code = filled(setting('pilots.id_code')) ? setting('pilots.id_code') : optional($this->airline)->icao;
return $ident_code.str_pad($this->pilot_id, $length, '0', STR_PAD_LEFT); return $this->airline->icao.str_pad($this->pilot_id, $length, '0', STR_PAD_LEFT);
} }
/** /**
@@ -154,7 +145,7 @@ class User extends Authenticatable
$first_name = $name_parts[0]; $first_name = $name_parts[0];
$last_name = $name_parts[$count - 1]; $last_name = $name_parts[$count - 1];
return $first_name.' '.mb_substr($last_name, 0, 1); return $first_name.' '.$last_name[0];
} }
/** /**
@@ -200,7 +191,8 @@ class User extends Authenticatable
{ {
$default = config('gravatar.default'); $default = config('gravatar.default');
$uri = config('gravatar.url').md5(strtolower(trim($this->email))).'?d='.urlencode($default); $uri = config('gravatar.url')
.md5(strtolower(trim($this->email))).'?d='.urlencode($default);
if ($size !== null) { if ($size !== null) {
$uri .= '&s='.$size; $uri .= '&s='.$size;
@@ -273,14 +265,4 @@ class User extends Authenticatable
{ {
return $this->belongsTo(Rank::class, 'rank_id'); return $this->belongsTo(Rank::class, 'rank_id');
} }
public function typeratings()
{
return $this->belongsToMany(Typerating::class, 'typerating_user', 'user_id', 'typerating_id');
}
public function rated_subfleets()
{
return $this->hasManyDeep(Subfleet::class, ['typerating_user', Typerating::class, 'typerating_subfleet']);
}
} }
-8
View File
@@ -22,14 +22,6 @@ class UserFieldValue extends Model
public static $rules = []; public static $rules = [];
/**
* Return related field's name along with field values
*/
public function getNameAttribute(): string
{
return optional($this->field)->name;
}
/** /**
* Foreign Keys * Foreign Keys
*/ */
@@ -11,16 +11,14 @@ use Carbon\Carbon;
*/ */
class DiscordMessage class DiscordMessage
{ {
const COLOR_SUCCESS = '0B6623'; const COLOR_SUCCESS = '#0B6623';
const COLOR_WARNING = 'FD6A02'; const COLOR_WARNING = '#FD6A02';
const COLOR_ERROR = 'ED2939'; const COLOR_ERROR = '#ED2939';
public $webhook_url; public $webhook_url;
protected $title; protected $title;
protected $url; protected $url;
protected $thumbnail = [];
protected $image = [];
protected $description; protected $description;
protected $timestamp; protected $timestamp;
protected $footer; protected $footer;
@@ -28,43 +26,30 @@ class DiscordMessage
protected $author = []; protected $author = [];
protected $fields = []; protected $fields = [];
// Supply the webhook URL that this should be going to /**
* Supply the webhook URL that this should be going to
*/
public function webhook(string $url): self public function webhook(string $url): self
{ {
$this->webhook_url = $url; $this->webhook_url = $url;
return $this; return $this;
} }
// Title of the embed /**
* Title of the notification
*/
public function title(string $title): self public function title(string $title): self
{ {
$this->title = $title; $this->title = $title;
return $this; return $this;
} }
// URL of the Title
public function url(string $url): self public function url(string $url): self
{ {
$this->url = $url; $this->url = $url;
return $this; return $this;
} }
// Thumbnail image (placed right side of embed)
// ['url' => '']
public function thumbnail(array $thumbnail): self
{
$this->thumbnail = $thumbnail;
return $this;
}
// Main image (placed bottom of embed)
// ['url' => '']
public function image(array $image): self
{
$this->image = $image;
return $this;
}
/** /**
* @param array|string $descriptionLines * @param array|string $descriptionLines
*/ */
@@ -78,15 +63,22 @@ class DiscordMessage
return $this; return $this;
} }
// Author details /**
// ['name' => '', 'url' => '', 'icon_url' => ''] * Set the author information:
* [
* 'name' => '',
* 'url' => '',
* 'icon_url' => '',
*/
public function author(array $author): self public function author(array $author): self
{ {
$this->author = $author; $this->author = $author;
return $this; return $this;
} }
// Fields /**
* Set the fields
*/
public function fields(array $fields): self public function fields(array $fields): self
{ {
$this->fields = []; $this->fields = [];
@@ -107,45 +99,32 @@ class DiscordMessage
return $this; return $this;
} }
// Fixed Success Color
public function success(): self public function success(): self
{ {
$this->color = hexdec('0B6623'); // static::COLOR_SUCCESS; $this->color = static::COLOR_SUCCESS;
return $this; return $this;
} }
// Fixed Warning
public function warning(): self public function warning(): self
{ {
$this->color = hexdec('FD6A02'); // static::COLOR_WARNING; $this->color = static::COLOR_WARNING;
return $this; return $this;
} }
// Fixed Error
public function error(): self public function error(): self
{ {
$this->color = hexdec('ED2939'); // static::COLOR_ERROR; $this->color = static::COLOR_ERROR;
return $this;
}
// Custom Color
public function color(string $embed_color): self
{
$this->color = hexdec($embed_color);
return $this; return $this;
} }
public function toArray(): array public function toArray(): array
{ {
$embeds = [ $embeds = [
'type' => 'rich',
'color' => $this->color,
'title' => $this->title, 'title' => $this->title,
'url' => $this->url, 'url' => $this->url,
'thumbnail' => $this->thumbnail, 'type' => 'rich',
'description' => $this->description, 'description' => $this->description,
'author' => $this->author, 'author' => $this->author,
'image' => $this->image,
'timestamp' => Carbon::now('UTC'), 'timestamp' => Carbon::now('UTC'),
]; ];
@@ -20,23 +20,14 @@ class DiscordWebhook
public function send($notifiable, Notification $notification) public function send($notifiable, Notification $notification)
{ {
$message = $notification->toDiscordChannel($notifiable); $message = $notification->toDiscordChannel($notifiable);
if ($message === null) { if ($message === null || empty($message->webhook_url)) {
//Log::debug('Discord notifications not configured, skipping'); Log::debug('Discord notifications not configured, skipping');
return; return;
} }
$webhook_url = $message->webhook_url;
if (empty($webhook_url)) {
$webhook_url = setting('notifications.discord_private_webhook_url');
if (empty($webhook_url)) {
//Log::debug('Discord notifications not configured, skipping');
return;
}
}
try { try {
$data = $message->toArray(); $data = $message->toArray();
$this->httpClient->post($webhook_url, $data); $this->httpClient->post($message->webhook_url, $data);
} catch (RequestException $e) { } catch (RequestException $e) {
$request = Psr7\Message::toString($e->getRequest()); $request = Psr7\Message::toString($e->getRequest());
$response = Psr7\Message::toString($e->getResponse()); $response = Psr7\Message::toString($e->getResponse());
@@ -4,6 +4,8 @@ namespace App\Notifications\Messages;
use App\Contracts\Notification; use App\Contracts\Notification;
use App\Models\User; use App\Models\User;
use App\Notifications\Channels\Discord\DiscordMessage;
use App\Notifications\Channels\Discord\DiscordWebhook;
use App\Notifications\Channels\MailChannel; use App\Notifications\Channels\MailChannel;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
@@ -30,21 +32,32 @@ class AdminUserRegistered extends Notification implements ShouldQueue
); );
} }
/**
* @param $notifiable
*
* @return string[]
*/
public function via($notifiable) public function via($notifiable)
{ {
return ['mail']; return ['mail', DiscordWebhook::class];
} }
/** /**
* @param $notifiable * Send a Discord notification
* *
* @return array * @param User $pirep
* @param mixed $user
*
* @return DiscordMessage|null
*/ */
public function toDiscordChannel($user): ?DiscordMessage
{
if (empty(setting('notifications.discord_private_webhook_url'))) {
return null;
}
$dm = new DiscordMessage();
return $dm->webhook(setting('notifications.discord_private_webhook_url'))
->success()
->title('New User Registered: '.$user->ident)
->fields([]);
}
public function toArray($notifiable) public function toArray($notifiable)
{ {
return [ return [
@@ -1,58 +0,0 @@
<?php
namespace App\Notifications\Messages\Broadcast;
use App\Contracts\Notification;
use App\Models\News;
use App\Notifications\Channels\Discord\DiscordMessage;
use Illuminate\Contracts\Queue\ShouldQueue;
class NewsAdded extends Notification implements ShouldQueue
{
private $news;
public function __construct(News $news)
{
parent::__construct();
$this->news = $news;
}
public function via($notifiable)
{
return ['discord_webhook'];
}
/**
* @param News $news
*
* @return DiscordMessage|null
*/
public function toDiscordChannel($news): ?DiscordMessage
{
$dm = new DiscordMessage();
return $dm->webhook(setting('notifications.discord_public_webhook_url'))
->success()
->title('News: '.$news->subject)
->author([
'name' => $news->user->ident.' - '.$news->user->name_private,
'url' => '',
'icon_url' => $news->user->resolveAvatarUrl(),
])
->description($news->body);
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
*
* @return array
*/
public function toArray($notifiable)
{
return [
'news_id' => $this->news->id,
];
}
}
@@ -1,74 +0,0 @@
<?php
namespace App\Notifications\Messages\Broadcast;
use App\Contracts\Notification;
use App\Models\User;
use App\Notifications\Channels\Discord\DiscordMessage;
use App\Notifications\Channels\MailChannel;
use Illuminate\Contracts\Queue\ShouldQueue;
/**
* Send a message to a Discord channel that a user was registered
*/
class UserRegistered extends Notification implements ShouldQueue
{
use MailChannel;
private $user;
/**
* Create a new notification instance.
*
* @param \App\Models\User $user
*/
public function __construct(User $user)
{
parent::__construct();
$this->user = $user;
}
/**
* @param $notifiable
*
* @return string[]
*/
public function via($notifiable)
{
return ['discord_webhook'];
}
/**
* Send a Discord notification
*
* @param $notifiable
*
* @return DiscordMessage|null
*/
public function toDiscordChannel($notifiable): ?DiscordMessage
{
$dm = new DiscordMessage();
return $dm->webhook(setting('notifications.discord_private_webhook_url'))
->success()
->title('New User Registered: '.$this->user->ident)
->author([
'name' => $this->user->ident.' - '.$this->user->name_private,
'url' => '',
'icon_url' => $this->user->resolveAvatarUrl(),
])
->fields([]);
}
/**
* @param $notifiable
*
* @return array
*/
public function toArray($notifiable)
{
return [
'user_id' => $this->user->id,
];
}
}
-53
View File
@@ -1,53 +0,0 @@
<?php
namespace App\Notifications\Messages;
use App\Contracts\Notification;
use App\Models\Pirep;
use App\Notifications\Channels\MailChannel;
use Illuminate\Contracts\Queue\ShouldQueue;
class PirepFiled extends Notification implements ShouldQueue
{
use MailChannel;
private $pirep;
/**
* Create a new notification instance.
*
* @param \App\Models\Pirep $pirep
*/
public function __construct(Pirep $pirep)
{
parent::__construct();
$this->pirep = $pirep;
$this->setMailable(
'New PIREP Submitted',
'notifications.mail.admin.pirep.submitted',
['pirep' => $this->pirep]
);
}
public function via($notifiable)
{
return ['mail'];
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
*
* @return array
*/
public function toArray($notifiable)
{
return [
'pirep_id' => $this->pirep->id,
'user_id' => $this->pirep->user_id,
];
}
}
@@ -1,6 +1,6 @@
<?php <?php
namespace App\Notifications\Messages\Broadcast; namespace App\Notifications\Messages;
use App\Contracts\Notification; use App\Contracts\Notification;
use App\Models\Pirep; use App\Models\Pirep;
@@ -48,9 +48,9 @@ class PirepPrefiled extends Notification implements ShouldQueue
return null; return null;
} }
$title = 'Flight '.$pirep->ident.' Prefiled'; $title = 'Flight '.$pirep->airline->code.$pirep->ident.' Prefiled';
$fields = [ $fields = [
'Flight' => $pirep->ident, 'Flight' => $pirep->airline->code.$pirep->ident,
'Departure Airport' => $pirep->dpt_airport_id, 'Departure Airport' => $pirep->dpt_airport_id,
'Arrival Airport' => $pirep->arr_airport_id, 'Arrival Airport' => $pirep->arr_airport_id,
'Equipment' => $pirep->aircraft->ident, 'Equipment' => $pirep->aircraft->ident,
@@ -1,6 +1,6 @@
<?php <?php
namespace App\Notifications\Messages\Broadcast; namespace App\Notifications\Messages;
use App\Contracts\Notification; use App\Contracts\Notification;
use App\Models\Enums\PirepStatus; use App\Models\Enums\PirepStatus;
@@ -44,7 +44,6 @@ class PirepStatusChanged extends Notification implements ShouldQueue
PirepStatus::LANDED => 'has landed', PirepStatus::LANDED => 'has landed',
PirepStatus::ARRIVED => 'has arrived', PirepStatus::ARRIVED => 'has arrived',
PirepStatus::CANCELLED => 'is cancelled', PirepStatus::CANCELLED => 'is cancelled',
PirepStatus::PAUSED => 'is paused',
PirepStatus::EMERG_DESCENT => 'in emergency descent', PirepStatus::EMERG_DESCENT => 'in emergency descent',
]; ];
@@ -77,12 +76,14 @@ class PirepStatusChanged extends Notification implements ShouldQueue
return null; return null;
} }
$title = 'Flight '.$pirep->ident.' '.self::$verbs[$pirep->status]; $title = 'Flight '.$pirep->airline->code.$pirep->ident.' '.self::$verbs[$pirep->status];
$fields = [ $fields = [
'Dep.Airport' => $pirep->dpt_airport_id, 'Flight' => $pirep->airline->code.$pirep->ident,
'Arr.Airport' => $pirep->arr_airport_id, 'Departure Airport' => $pirep->dpt_airport_id,
'Equipment' => $pirep->aircraft->ident, 'Arrival Airport' => $pirep->arr_airport_id,
'Flight Time' => Time::minutesToTimeString($pirep->flight_time), 'Equipment' => $pirep->aircraft->ident,
'Flight Time' => Time::minutesToTimeString($pirep->flight_time),
]; ];
// Show the distance, but include the planned distance if it's been set // Show the distance, but include the planned distance if it's been set
@@ -100,38 +101,25 @@ class PirepStatusChanged extends Notification implements ShouldQueue
$planned_distance = new Distance($pirep->planned_distance, $unit); $planned_distance = new Distance($pirep->planned_distance, $unit);
$pd = $planned_distance[$planned_distance->unit]; $pd = $planned_distance[$planned_distance->unit];
$fields['Distance'] .= '/'.$pd; $fields['Distance'] .= '/'.$pd;
} catch (NonNumericValue|NonStringUnitName $e) { } catch (NonNumericValue | NonStringUnitName $e) {
} }
} }
$fields['Distance'] .= ' '.$planned_distance->unit; $fields['Distance'] .= ' '.$planned_distance->unit;
} catch (NonNumericValue|NonStringUnitName $e) { } catch (NonNumericValue | NonStringUnitName $e) {
} }
} }
// User avatar, somehow $pirep->user->resolveAvatarUrl() is not being accepted by Discord as thumbnail
$user_avatar = !empty($pirep->user->avatar) ? $pirep->user->avatar->url : $pirep->user->gravatar(256);
// Proper coloring for the messages
// Pirep Filed > success, normals > warning, non-normals > error
$danger_types = [
PirepStatus::GRND_RTRN,
PirepStatus::DIVERTED,
PirepStatus::CANCELLED,
PirepStatus::PAUSED,
PirepStatus::EMERG_DESCENT,
];
$color = in_array($pirep->status, $danger_types, true) ? 'ED2939' : 'FD6A02';
$dm = new DiscordMessage(); $dm = new DiscordMessage();
return $dm->webhook(setting('notifications.discord_public_webhook_url')) return $dm->webhook(setting('notifications.discord_public_webhook_url'))
->color($color) ->success()
->title($title) ->title($title)
->description($pirep->user->discord_id ? 'Flight by <@'.$pirep->user->discord_id.'>' : '') ->description($pirep->user->discord_id ? 'Flight by <@'.$pirep->user->discord_id.'>' : '')
->thumbnail(['url' => $user_avatar]) ->url(route('frontend.pireps.show', [$pirep->id]))
->author([ ->author([
'name' => $pirep->user->ident.' - '.$pirep->user->name_private, 'name' => $pirep->user->ident.' - '.$pirep->user->name_private,
'url' => route('frontend.profile.show', [$pirep->user_id]), 'url' => route('frontend.profile.show', [$pirep->user_id]),
'icon_url' => $pirep->user->resolveAvatarUrl(),
]) ])
->fields($fields); ->fields($fields);
} }
@@ -1,18 +1,22 @@
<?php <?php
namespace App\Notifications\Messages\Broadcast; namespace App\Notifications\Messages;
use App\Contracts\Notification; use App\Contracts\Notification;
use App\Models\Pirep; use App\Models\Pirep;
use App\Notifications\Channels\Discord\DiscordMessage; use App\Notifications\Channels\Discord\DiscordMessage;
use App\Notifications\Channels\Discord\DiscordWebhook;
use App\Notifications\Channels\MailChannel;
use App\Support\Units\Distance; use App\Support\Units\Distance;
use App\Support\Units\Time; use App\Support\Units\Time;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use PhpUnitsOfMeasure\Exception\NonNumericValue; use PhpUnitsOfMeasure\Exception\NonNumericValue;
use PhpUnitsOfMeasure\Exception\NonStringUnitName; use PhpUnitsOfMeasure\Exception\NonStringUnitName;
class PirepFiled extends Notification implements ShouldQueue class PirepSubmitted extends Notification implements ShouldQueue
{ {
use MailChannel;
private $pirep; private $pirep;
/** /**
@@ -25,11 +29,17 @@ class PirepFiled extends Notification implements ShouldQueue
parent::__construct(); parent::__construct();
$this->pirep = $pirep; $this->pirep = $pirep;
$this->setMailable(
'New PIREP Submitted',
'notifications.mail.admin.pirep.submitted',
['pirep' => $this->pirep]
);
} }
public function via($notifiable) public function via($notifiable)
{ {
return ['discord_webhook']; return ['mail', DiscordWebhook::class];
} }
/** /**
@@ -41,40 +51,42 @@ class PirepFiled extends Notification implements ShouldQueue
*/ */
public function toDiscordChannel($pirep): ?DiscordMessage public function toDiscordChannel($pirep): ?DiscordMessage
{ {
$title = 'Flight '.$pirep->ident.' Filed'; if (empty(setting('notifications.discord_public_webhook_url'))) {
return null;
}
$title = 'Flight '.$pirep->airline->code.$pirep->ident.' Filed';
$fields = [ $fields = [
'Dep.Airport' => $pirep->dpt_airport_id, 'Flight' => $pirep->airline->code.$pirep->ident,
'Arr.Airport' => $pirep->arr_airport_id, 'Departure Airport' => $pirep->dpt_airport_id,
'Equipment' => $pirep->aircraft->ident, 'Arrival Airport' => $pirep->arr_airport_id,
'Flight Time' => Time::minutesToTimeString($pirep->flight_time), 'Equipment' => $pirep->aircraft->ident,
'Flight Time (Planned)' => Time::minutesToTimeString($pirep->planned_flight_time),
]; ];
if ($pirep->distance) { if ($pirep->planned_distance) {
try { try {
$distance = new Distance( $planned_distance = new Distance(
$pirep->distance, $pirep->planned_distance,
config('phpvms.internal_units.distance') config('phpvms.internal_units.distance')
); );
$pd = $distance[$distance->unit].' '.$distance->unit; $pd = $planned_distance[$planned_distance->unit].' '.$planned_distance->unit;
$fields['Distance'] = $pd; $fields['Distance (Planned)'] = $pd;
} catch (NonNumericValue|NonStringUnitName $e) { } catch (NonNumericValue | NonStringUnitName $e) {
} }
} }
// User avatar, somehow $pirep->user->resolveAvatarUrl() is not being accepted by Discord as thumbnail
$user_avatar = !empty($pirep->user->avatar) ? $pirep->user->avatar->url : $pirep->user->gravatar(256);
$dm = new DiscordMessage(); $dm = new DiscordMessage();
return $dm->webhook(setting('notifications.discord_public_webhook_url')) return $dm->webhook(setting('notifications.discord_public_webhook_url'))
->success() ->success()
->title($title) ->title($title)
->description($pirep->user->discord_id ? 'Flight by <@'.$pirep->user->discord_id.'>' : '') ->description($pirep->user->discord_id ? 'Flight by <@'.$pirep->user->discord_id.'>' : '')
->thumbnail(['url' => $user_avatar]) ->url(route('frontend.pireps.show', [$pirep->id]))
->image(['url' => $pirep->airline->logo])
->author([ ->author([
'name' => $pirep->user->ident.' - '.$pirep->user->name_private, 'name' => $pirep->user->ident.' - '.$pirep->user->name_private,
'url' => route('frontend.profile.show', [$pirep->user_id]), 'url' => route('frontend.profile.show', [$pirep->user_id]),
'icon_url' => $pirep->user->resolveAvatarUrl(),
]) ])
->fields($fields); ->fields($fields);
} }
+18 -56
View File
@@ -11,7 +11,6 @@ use App\Events\PirepRejected;
use App\Events\PirepStatusChange; use App\Events\PirepStatusChange;
use App\Events\UserRegistered; use App\Events\UserRegistered;
use App\Events\UserStateChanged; use App\Events\UserStateChanged;
use App\Models\Enums\PirepStatus;
use App\Models\Enums\UserState; use App\Models\Enums\UserState;
use App\Models\User; use App\Models\User;
use App\Notifications\Messages\UserRejected; use App\Notifications\Messages\UserRejected;
@@ -59,8 +58,8 @@ class NotificationEventsHandler extends Listener
} }
try { try {
// $this->notifyUser($user, $notification); $this->notifyUser($user, $notification);
Notification::send([$user], $notification); // Notification::send([$user], $notification);
} catch (Exception $e) { } catch (Exception $e) {
Log::emergency('Error emailing admin ('.$user->email.'). Error='.$e->getMessage()); Log::emergency('Error emailing admin ('.$user->email.'). Error='.$e->getMessage());
} }
@@ -135,10 +134,10 @@ class NotificationEventsHandler extends Listener
*/ */
$this->notifyAdmins(new Messages\AdminUserRegistered($event->user)); $this->notifyAdmins(new Messages\AdminUserRegistered($event->user));
/* /**
* Broadcast notifications * Discord and other notifications
*/ */
Notification::send([$event->user], new Messages\Broadcast\UserRegistered($event->user)); Notification::send([$event->user], new Messages\AdminUserRegistered($event->user));
} }
/** /**
@@ -162,42 +161,21 @@ class NotificationEventsHandler extends Listener
} }
/** /**
* Prefile notification. Disabled intentionally, No need to send it to Discord * Prefile notification
*/ */
public function onPirepPrefile(PirepPrefiled $event): void public function onPirepPrefile(PirepPrefiled $event): void
{ {
Log::info('NotificationEvents::onPirepPrefile: '.$event->pirep->id.' prefiled'); Log::info('NotificationEvents::onPirepPrefile: '.$event->pirep->id.' prefiled');
Notification::send([$event->pirep], new Messages\PirepPrefiled($event->pirep));
/*
* Broadcast notifications
*/
// Notification::send([$event->pirep], new Messages\Broadcast\PirepPrefiled($event->pirep));
} }
/** /**
* Status Change notification. * Status Change notification
* Reduced the messages (Boarding, Pushback, TakeOff, Landing and non-normals only)
* If needed array can be tied to a setting at admin side for further customization
*/ */
public function onPirepStatusChange(PirepStatusChange $event): void public function onPirepStatusChange(PirepStatusChange $event): void
{ {
Log::info('NotificationEvents::onPirepStatusChange: '.$event->pirep->id.' status changed'); Log::info('NotificationEvents::onPirepStatusChange: '.$event->pirep->id.' prefiled');
Notification::send([$event->pirep], new Messages\PirepStatusChanged($event->pirep));
$message_types = [
PirepStatus::BOARDING,
PirepStatus::PUSHBACK_TOW,
PirepStatus::GRND_RTRN,
PirepStatus::TAKEOFF,
PirepStatus::LANDED,
PirepStatus::DIVERTED,
PirepStatus::CANCELLED,
PirepStatus::PAUSED,
PirepStatus::EMERG_DESCENT,
];
if (setting('notifications.discord_pirep_status', true) && in_array($event->pirep->status, $message_types, true)) {
Notification::send([$event->pirep], new Messages\Broadcast\PirepStatusChanged($event->pirep));
}
} }
/** /**
@@ -208,14 +186,8 @@ class NotificationEventsHandler extends Listener
public function onPirepFile(PirepFiled $event): void public function onPirepFile(PirepFiled $event): void
{ {
Log::info('NotificationEvents::onPirepFile: '.$event->pirep->id.' filed'); Log::info('NotificationEvents::onPirepFile: '.$event->pirep->id.' filed');
if (setting('notifications.mail_pirep_admin', true)) { $this->notifyAdmins(new Messages\PirepSubmitted($event->pirep));
$this->notifyAdmins(new Messages\PirepFiled($event->pirep)); Notification::send([$event->pirep], new Messages\PirepSubmitted($event->pirep));
}
/*
* Broadcast notifications
*/
Notification::send([$event->pirep], new Messages\Broadcast\PirepFiled($event->pirep));
} }
/** /**
@@ -225,10 +197,8 @@ class NotificationEventsHandler extends Listener
*/ */
public function onPirepAccepted(PirepAccepted $event): void public function onPirepAccepted(PirepAccepted $event): void
{ {
if (setting('notifications.mail_pirep_user_ack', true)) { Log::info('NotificationEvents::onPirepAccepted: '.$event->pirep->id.' accepted');
Log::info('NotificationEvents::onPirepAccepted: '.$event->pirep->id.' accepted'); $this->notifyUser($event->pirep->user, new Messages\PirepAccepted($event->pirep));
$this->notifyUser($event->pirep->user, new Messages\PirepAccepted($event->pirep));
}
} }
/** /**
@@ -238,10 +208,8 @@ class NotificationEventsHandler extends Listener
*/ */
public function onPirepRejected(PirepRejected $event): void public function onPirepRejected(PirepRejected $event): void
{ {
if (setting('notifications.mail_pirep_user_rej', true)) { Log::info('NotificationEvents::onPirepRejected: '.$event->pirep->id.' rejected');
Log::info('NotificationEvents::onPirepRejected: '.$event->pirep->id.' rejected'); $this->notifyUser($event->pirep->user, new Messages\PirepRejected($event->pirep));
$this->notifyUser($event->pirep->user, new Messages\PirepRejected($event->pirep));
}
} }
/** /**
@@ -252,13 +220,7 @@ class NotificationEventsHandler extends Listener
public function onNewsAdded(NewsAdded $event): void public function onNewsAdded(NewsAdded $event): void
{ {
Log::info('NotificationEvents::onNewsAdded'); Log::info('NotificationEvents::onNewsAdded');
if (setting('notifications.mail_news', true)) { $this->notifyAllUsers(new Messages\NewsAdded($event->news));
$this->notifyAllUsers(new Messages\NewsAdded($event->news)); Notification::send([$event->news], new Messages\NewsAdded($event->news));
}
/*
* Broadcast notifications
*/
Notification::send([$event->news], new Messages\Broadcast\NewsAdded($event->news));
} }
} }
-7
View File
@@ -2,12 +2,10 @@
namespace App\Providers; namespace App\Providers;
use App\Notifications\Channels\Discord\DiscordWebhook;
use App\Services\ModuleService; use App\Services\ModuleService;
use App\Support\ThemeViewFinder; use App\Support\ThemeViewFinder;
use App\Support\Utils; use App\Support\Utils;
use Illuminate\Pagination\Paginator; use Illuminate\Pagination\Paginator;
use Illuminate\Support\Facades\Notification;
use Illuminate\Support\Facades\Schema; use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\View; use Illuminate\Support\Facades\View;
use Illuminate\Support\ServiceProvider; use Illuminate\Support\ServiceProvider;
@@ -17,13 +15,8 @@ class AppServiceProvider extends ServiceProvider
public function boot(): void public function boot(): void
{ {
Schema::defaultStringLength(191); Schema::defaultStringLength(191);
Paginator::useBootstrap(); Paginator::useBootstrap();
View::share('moduleSvc', app(ModuleService::class)); View::share('moduleSvc', app(ModuleService::class));
Notification::extend('discord_webhook', function ($app) {
return app(DiscordWebhook::class);
});
} }
/** /**
+9 -12
View File
@@ -12,12 +12,9 @@ use App\Cron\Nightly\PilotLeave;
use App\Cron\Nightly\RecalculateBalances; use App\Cron\Nightly\RecalculateBalances;
use App\Cron\Nightly\RecalculateStats; use App\Cron\Nightly\RecalculateStats;
use App\Cron\Nightly\SetActiveFlights; use App\Cron\Nightly\SetActiveFlights;
use App\Events\CronFifteenMinute;
use App\Events\CronFiveMinute;
use App\Events\CronHourly; use App\Events\CronHourly;
use App\Events\CronMonthly; use App\Events\CronMonthly;
use App\Events\CronNightly; use App\Events\CronNightly;
use App\Events\CronThirtyMinute;
use App\Events\CronWeekly; use App\Events\CronWeekly;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider; use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
@@ -27,15 +24,6 @@ use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvi
class CronServiceProvider extends ServiceProvider class CronServiceProvider extends ServiceProvider
{ {
protected $listen = [ protected $listen = [
CronFiveMinute::class => [],
CronFifteenMinute::class => [],
CronThirtyMinute::class => [],
CronHourly::class => [
DeletePireps::class,
RemoveExpiredBids::class,
RemoveExpiredLiveFlights::class,
ClearExpiredSimbrief::class,
],
CronNightly::class => [ CronNightly::class => [
ApplyExpenses::class, ApplyExpenses::class,
RecalculateBalances::class, RecalculateBalances::class,
@@ -44,10 +32,19 @@ class CronServiceProvider extends ServiceProvider
RecalculateStats::class, RecalculateStats::class,
NewVersionCheck::class, NewVersionCheck::class,
], ],
CronWeekly::class => [ CronWeekly::class => [
], ],
CronMonthly::class => [ CronMonthly::class => [
\App\Cron\Monthly\ApplyExpenses::class, \App\Cron\Monthly\ApplyExpenses::class,
], ],
CronHourly::class => [
DeletePireps::class,
RemoveExpiredBids::class,
RemoveExpiredLiveFlights::class,
ClearExpiredSimbrief::class,
],
]; ];
} }
-6
View File
@@ -3,13 +3,11 @@
namespace App\Providers; namespace App\Providers;
use App\Events\Expenses; use App\Events\Expenses;
use App\Events\Fares;
use App\Events\PirepFiled; use App\Events\PirepFiled;
use App\Events\UserStatsChanged; use App\Events\UserStatsChanged;
use App\Listeners\AwardHandler; use App\Listeners\AwardHandler;
use App\Listeners\BidEventHandler; use App\Listeners\BidEventHandler;
use App\Listeners\ExpenseListener; use App\Listeners\ExpenseListener;
use App\Listeners\FareListener;
use App\Listeners\FinanceEventHandler; use App\Listeners\FinanceEventHandler;
use App\Listeners\PirepEventsHandler; use App\Listeners\PirepEventsHandler;
use App\Listeners\UserStateListener; use App\Listeners\UserStateListener;
@@ -27,10 +25,6 @@ class EventServiceProvider extends ServiceProvider
ExpenseListener::class, ExpenseListener::class,
], ],
Fares::class => [
FareListener::class,
],
PirepFiled::class => [ PirepFiled::class => [
UserStateListener::class, UserStateListener::class,
], ],
-33
View File
@@ -376,21 +376,6 @@ class RouteServiceProvider extends ServiceProvider
], 'settings', 'SettingsController@update') ], 'settings', 'SettingsController@update')
->name('settings.update')->middleware('ability:admin,settings'); ->name('settings.update')->middleware('ability:admin,settings');
// Type Ratings
Route::resource('typeratings', 'TypeRatingController')->middleware('ability:admin,typeratings');
Route::match([
'get',
'post',
'put',
'delete',
], 'typeratings/{id}/subfleets', 'TypeRatingController@subfleets')->middleware('ability:admin,typeratings');
Route::match([
'get',
'post',
'put',
'delete',
], 'typeratings/{id}/users', 'TypeRatingController@users')->middleware('ability:admin,typeratings');
// maintenance // maintenance
Route::match(['get'], 'maintenance', 'MaintenanceController@index') Route::match(['get'], 'maintenance', 'MaintenanceController@index')
->name('maintenance.index')->middleware('ability:admin,maintenance'); ->name('maintenance.index')->middleware('ability:admin,maintenance');
@@ -441,13 +426,6 @@ class RouteServiceProvider extends ServiceProvider
'delete', 'delete',
], 'subfleets/{id}/ranks', 'SubfleetController@ranks')->middleware('ability:admin,fleet'); ], 'subfleets/{id}/ranks', 'SubfleetController@ranks')->middleware('ability:admin,fleet');
Route::match([
'get',
'post',
'put',
'delete',
], 'subfleets/{id}/typeratings', 'SubfleetController@typeratings')->middleware('ability:admin,fleet');
Route::resource('subfleets', 'SubfleetController')->middleware('ability:admin,fleet'); Route::resource('subfleets', 'SubfleetController')->middleware('ability:admin,fleet');
/** /**
@@ -461,13 +439,6 @@ class RouteServiceProvider extends ServiceProvider
Route::resource('users', 'UserController')->middleware('ability:admin,users'); Route::resource('users', 'UserController')->middleware('ability:admin,users');
Route::match([
'get',
'post',
'put',
'delete',
], 'users/{id}/typeratings', 'UserController@typeratings')->middleware('ability:admin,users');
// defaults // defaults
Route::get('', ['uses' => 'DashboardController@index']) Route::get('', ['uses' => 'DashboardController@index'])
->middleware('update_pending', 'ability:admin,admin-access'); ->middleware('update_pending', 'ability:admin,admin-access');
@@ -613,10 +584,6 @@ class RouteServiceProvider extends ServiceProvider
Route::get('user/fleet', 'UserController@fleet'); Route::get('user/fleet', 'UserController@fleet');
Route::get('user/pireps', 'UserController@pireps'); Route::get('user/pireps', 'UserController@pireps');
Route::get('bids', 'UserController@bids');
Route::get('bids/{id}', 'UserController@get_bid');
Route::get('user/bids/{id}', 'UserController@get_bid');
Route::get('user/bids', 'UserController@bids'); Route::get('user/bids', 'UserController@bids');
Route::put('user/bids', 'UserController@bids'); Route::put('user/bids', 'UserController@bids');
Route::post('user/bids', 'UserController@bids'); Route::post('user/bids', 'UserController@bids');
+3 -3
View File
@@ -69,11 +69,11 @@ class AcarsRepository extends Repository
->where(['state' => PirepState::IN_PROGRESS]); ->where(['state' => PirepState::IN_PROGRESS]);
if ($live_time !== null && $live_time > 0) { if ($live_time !== null && $live_time > 0) {
$st = Carbon::now()->subHours($live_time); $st = Carbon::now('UTC')->subHours($live_time);
$q = $q->where('updated_at', '>=', $st); $q = $q->whereDate('created_at', '>=', $st);
} }
$q = $q->orderBy('updated_at', 'desc'); $q = $q->orderBy('created_at', 'desc');
return $q->get(); return $q->get();
} }
-16
View File
@@ -18,10 +18,8 @@ class FlightRepository extends Repository implements CacheableInterface
protected $fieldSearchable = [ protected $fieldSearchable = [
'arr_airport_id', 'arr_airport_id',
'callsign',
'distance', 'distance',
'dpt_airport_id', 'dpt_airport_id',
'flight_time',
'flight_type', 'flight_type',
'flight_number' => 'like', 'flight_number' => 'like',
'route_code' => 'like', 'route_code' => 'like',
@@ -96,10 +94,6 @@ class FlightRepository extends Repository implements CacheableInterface
$where['flight_number'] = $request->input('flight_number'); $where['flight_number'] = $request->input('flight_number');
} }
if ($request->filled('callsign')) {
$where['callsign'] = $request->input('callsign');
}
if ($request->filled('flight_type') && $request->input('flight_type') !== '0') { if ($request->filled('flight_type') && $request->input('flight_type') !== '0') {
$where['flight_type'] = $request->input('flight_type'); $where['flight_type'] = $request->input('flight_type');
} }
@@ -134,16 +128,6 @@ class FlightRepository extends Repository implements CacheableInterface
$where[] = ['distance', '<=', $request->input('dlt')]; $where[] = ['distance', '<=', $request->input('dlt')];
} }
// Time, greater than
if ($request->filled('tgt')) {
$where[] = ['flight_time', '>=', $request->input('tgt')];
}
// Time, less than
if ($request->filled('tlt')) {
$where[] = ['flight_time', '<=', $request->input('tlt')];
}
// Do a special query for finding the child subfleets // Do a special query for finding the child subfleets
if ($request->filled('subfleet_id')) { if ($request->filled('subfleet_id')) {
$relations['subfleets'] = [ $relations['subfleets'] = [

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