Compare commits

..
Author SHA1 Message Date
snyk-bot a5a1a1f7aa fix: package.json & package-lock.json to reduce vulnerabilities
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-JS-POSTCSS-1255640
2021-04-27 02:24:10 +00:00
397 changed files with 57399 additions and 35165 deletions
+2 -16
View File
@@ -23,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
@@ -31,7 +30,6 @@ declare -a remove_files=(
intellij_style.xml intellij_style.xml
config.php config.php
docker-compose.yml docker-compose.yml
docker-compose.local.yml
Makefile Makefile
phpcs.xml phpcs.xml
phpunit.xml phpunit.xml
@@ -71,25 +69,13 @@ 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"
tar2zip $TAR_NAME
cd $BASE_DIR;
zip -r $ZIP_NAME ./
sha256sum $ZIP_NAME >"$ZIP_NAME.sha256" sha256sum $ZIP_NAME >"$ZIP_NAME.sha256"
mv $ZIP_NAME /tmp
mv "$ZIP_NAME.sha256" /tmp
ls -al /tmp ls -al /tmp
echo "Moving to dist" echo "Moving to dist"
+6 -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']
name: PHP ${{ matrix.php-versions }} name: PHP ${{ matrix.php-versions }}
env: env:
extensions: intl, pcov, mbstring extensions: intl, pcov, mbstring
@@ -41,6 +41,7 @@ jobs:
with: with:
path: ${{ steps.composer-cache.outputs.dir }} path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: ${{ runner.os }}-composer-
# Configure PHP # Configure PHP
- name: Setup PHP - name: Setup PHP
@@ -78,8 +79,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 +117,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 +180,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);
-4
View File
@@ -1,4 +0,0 @@
This file was added by Shift #54503 in order to open a
Pull Request since no other commits were made.
You should remove this file.
+5 -13
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
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
@@ -17,21 +14,16 @@ RUN docker-php-ext-install \
calendar \ calendar \
intl \ intl \
pdo_mysql \ pdo_mysql \
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
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
+20 -3
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
@@ -100,9 +109,17 @@ reset-installer:
@php artisan database:create --reset @php artisan database:create --reset
@php artisan migrate:refresh --seed @php artisan migrate:refresh --seed
.PHONY: docker-test .PHONY: docker
docker-test: docker:
@docker compose -f docker-compose.yml -f docker-compose.local.yml up @mkdir -p $(CURR_PATH)/tmp/mysql
-docker rm -f phpvms
docker build -t phpvms .
docker run --name=phpvms \
-v $(CURR_PATH):/var/www/ \
-v $(CURR_PATH)/tmp/mysql:/var/lib/mysql \
-p 8080:80 \
phpvms
.PHONY: docker-clean .PHONY: docker-clean
docker-clean: docker-clean:
+6 -9
View File
@@ -30,16 +30,15 @@ A full distribution, with all of the composer dependencies, is available at this
[View installation details](https://docs.phpvms.net/installation/installation) [View installation details](https://docs.phpvms.net/installation/installation)
## Development Environment with Docker ## Development Environment
A full development environment can be brought up using Docker, without having to install composer/npm locally A full development environment can be brought up using Docker:
```bash ```bash
make docker-test composer install
npm install
# **OR** with docker-compose directly docker-compose build
docker-compose up
docker-compose -f docker-compose.yml -f docker-compose.local.yml up
``` ```
Then go to `http://localhost`. If you're using dnsmasq, the `app` container is listening on `phpvms.test`, or you can add to your `/etc/hosts` file: Then go to `http://localhost`. If you're using dnsmasq, the `app` container is listening on `phpvms.test`, or you can add to your `/etc/hosts` file:
@@ -48,8 +47,6 @@ Then go to `http://localhost`. If you're using dnsmasq, the `app` container is l
127.0.0.1 phpvms.test 127.0.0.1 phpvms.test
``` ```
The `docker-compose.local.yml` overrides the `app` section in `docker-compose.yml`. The standard `docker-compose.yml` can be used if you want to deploy from the image, or as a template for your own Dockerized deployments.
### Building JS/CSS assets ### Building JS/CSS assets
Yarn is required, run: Yarn is required, run:
-32
View File
@@ -1,32 +0,0 @@
<?php
namespace App\Console\Commands;
use App;
use App\Contracts\Command;
class EmailTest extends Command
{
protected $signature = 'phpvms:email-test';
protected $description = 'Send a test notification to admins';
/**
* Run dev related commands
*
* @throws \Symfony\Component\HttpFoundation\File\Exception\FileException
*/
public function handle()
{
/** @var App\Notifications\NotificationEventsHandler $eventHandler */
$eventHandler = app(App\Notifications\NotificationEventsHandler::class);
$news = new App\Models\News();
$news->user_id = 1;
$news->subject = 'Test News';
$news->body = 'Test Body';
$news->save();
$newsEvent = new App\Events\NewsAdded($news);
$eventHandler->onNewsAdded($newsEvent);
}
}
-38
View File
@@ -1,38 +0,0 @@
<?php
namespace App\Console\Commands;
use App;
use App\Contracts\Command;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Log;
class ProcessQueue extends Command
{
protected $signature = 'queue:cron';
protected $description = 'Process the queue from a cron job';
/**
* Run the queue tasks
*/
public function handle()
{
Artisan::call('queue:work', [
'--sansdaemon' => null,
'--stop-when-empty' => null,
]);
Log::info(Artisan::output());
///** @var App\Support\WorkCommand $queueWorker */
//$queueWorker = new App\Support\WorkCommand(app('queue.worker'), app('cache.store'));
//$queueWorker->setInput($queueWorker->createInputFromArguments([]));
//$queueWorker->handle();
/*$output = $this->call('queue:work', [
'--stop-when-empty' => null,
]);
Log::info($output);*/
}
}
-25
View File
@@ -1,25 +0,0 @@
<?php
namespace App\Console\Cron;
use App\Contracts\Command;
use Illuminate\Support\Facades\Artisan;
/**
* This just calls the CronHourly event, so all of the
* listeners, etc can just be called to run those tasks
*/
class JobQueue extends Command
{
protected $signature = 'cron:queue';
protected $description = 'Run the cron queue tasks';
protected $schedule;
public function handle(): void
{
$this->redirectLoggingToFile('cron');
Artisan::call('queue:cron');
$this->info(Artisan::output());
}
}
-8
View File
@@ -3,7 +3,6 @@
namespace App\Console; namespace App\Console;
use App\Console\Cron\Hourly; use App\Console\Cron\Hourly;
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\Weekly; use App\Console\Cron\Weekly;
@@ -26,13 +25,6 @@ class Kernel extends ConsoleKernel
*/ */
protected function schedule(Schedule $schedule): void protected function schedule(Schedule $schedule): void
{ {
// If not using the queue worker then run those via cron
if (!config('queue.worker', false)) {
$schedule->command(JobQueue::class)
->everyMinute()
->withoutOverlapping();
}
$schedule->command(Nightly::class)->dailyAt('01:00'); $schedule->command(Nightly::class)->dailyAt('01:00');
$schedule->command(Weekly::class)->weeklyOn(0); $schedule->command(Weekly::class)->weeklyOn(0);
$schedule->command(Monthly::class)->monthlyOn(1); $schedule->command(Monthly::class)->monthlyOn(1);
+2 -2
View File
@@ -24,9 +24,9 @@ abstract class Command extends \Illuminate\Console\Command
parent::__construct(); parent::__construct();
// Running in the console but not in the tests // Running in the console but not in the tests
/*if (app()->runningInConsole() && env('APP_ENV') !== 'testing') { if (app()->runningInConsole() && env('APP_ENV') !== 'testing') {
$this->redirectLoggingToFile('stdout'); $this->redirectLoggingToFile('stdout');
}*/ }
} }
/** /**
-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) {
+4 -12
View File
@@ -2,9 +2,9 @@
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;
use Illuminate\Support\Facades\Log;
class Notification extends \Illuminate\Notifications\Notification implements ShouldQueue class Notification extends \Illuminate\Notifications\Notification implements ShouldQueue
{ {
@@ -17,14 +17,14 @@ class Notification extends \Illuminate\Notifications\Notification implements Sho
{ {
// Look in the notifications.channels config and see where this particular // Look in the notifications.channels config and see where this particular
// notification can go. Map it to $channels // notification can go. Map it to $channels
/*$klass = static::class; $klass = static::class;
$notif_config = config('notifications.channels', []); $notif_config = config('notifications.channels', []);
if (!array_key_exists($klass, $notif_config)) { if (!array_key_exists($klass, $notif_config)) {
Log::error('Notification type '.$klass.' missing from notifications config, defaulting to mail'); Log::error('Notification type '.$klass.' missing from notifications config, defaulting to mail');
return; return;
} }
$this->channels = $notif_config[$klass];*/ $this->channels = $notif_config[$klass];
} }
/** /**
@@ -34,16 +34,8 @@ class Notification extends \Illuminate\Notifications\Notification implements Sho
* *
* @return array * @return array
*/ */
/*public function via($notifiable) public function via($notifiable)
{ {
return $this->channels; return $this->channels;
}*/
/**
* @return DiscordMessage|null
*/
public function toDiscordChannel($notifiable): ?DiscordMessage
{
return null;
} }
} }
+11 -12
View File
@@ -2,14 +2,11 @@
namespace App\Contracts; namespace App\Contracts;
use Exception;
use Illuminate\Validation\Validator; use Illuminate\Validation\Validator;
use function is_array;
use Prettus\Repository\Eloquent\BaseRepository; use Prettus\Repository\Eloquent\BaseRepository;
use Prettus\Repository\Exceptions\RepositoryException;
/** /**
* @mixin BaseRepository * @mixin \Prettus\Repository\Eloquent\BaseRepository
*/ */
abstract class Repository extends BaseRepository abstract class Repository extends BaseRepository
{ {
@@ -23,8 +20,8 @@ abstract class Repository extends BaseRepository
{ {
try { try {
return $this->find($id, $columns); return $this->find($id, $columns);
} catch (Exception $e) { } catch (\Exception $e) {
return null; return;
} }
} }
@@ -35,7 +32,11 @@ abstract class Repository extends BaseRepository
*/ */
public function validate($values) public function validate($values)
{ {
$validator = Validator::make($values, $this->model()->rules); $validator = Validator::make(
$values,
$this->model()->rules
);
if ($validator->fails()) { if ($validator->fails()) {
return $validator->messages(); return $validator->messages();
} }
@@ -49,8 +50,6 @@ abstract class Repository extends BaseRepository
* @param int $count * @param int $count
* @param string $sort_by created_at (default) or updated_at * @param string $sort_by created_at (default) or updated_at
* *
* @throws RepositoryException
*
* @return mixed * @return mixed
*/ */
public function recent($count = null, $sort_by = 'created_at') public function recent($count = null, $sort_by = 'created_at')
@@ -72,7 +71,7 @@ abstract class Repository extends BaseRepository
return $this->scopeQuery(function ($query) use ($where, $sort_by, $order_by) { return $this->scopeQuery(function ($query) use ($where, $sort_by, $order_by) {
$q = $query->where($where); $q = $query->where($where);
// See if there are multi-column sorts // See if there are multi-column sorts
if (is_array($sort_by)) { if (\is_array($sort_by)) {
foreach ($sort_by as $key => $sort) { foreach ($sort_by as $key => $sort) {
$q = $q->orderBy($key, $sort); $q = $q->orderBy($key, $sort);
} }
@@ -99,7 +98,7 @@ abstract class Repository extends BaseRepository
return $this->scopeQuery(function ($query) use ($col, $values, $sort_by, $order_by) { return $this->scopeQuery(function ($query) use ($col, $values, $sort_by, $order_by) {
$q = $query->whereNotIn($col, $values); $q = $query->whereNotIn($col, $values);
// See if there are multi-column sorts // See if there are multi-column sorts
if (is_array($sort_by)) { if (\is_array($sort_by)) {
foreach ($sort_by as $key => $sort) { foreach ($sort_by as $key => $sort) {
$q = $q->orderBy($key, $sort); $q = $q->orderBy($key, $sort);
} }
@@ -119,7 +118,7 @@ abstract class Repository extends BaseRepository
* @param array $columns * @param array $columns
* @param string $method * @param string $method
* *
* @throws RepositoryException * @throws \Prettus\Repository\Exceptions\RepositoryException
* *
* @return mixed * @return mixed
*/ */
-27
View File
@@ -2,10 +2,7 @@
namespace App\Contracts; namespace App\Contracts;
use App\Support\Resources\CustomAnonymousResourceCollection;
use App\Support\Resources\CustomPaginatedResourceResponse;
use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Pagination\AbstractPaginator;
/** /**
* Base class for a resource/response * Base class for a resource/response
@@ -29,28 +26,4 @@ class Resource extends JsonResource
} }
} }
} }
/**
* Customize the response to exclude all the extra data that isn't used. Based on:
* https://gist.github.com/derekphilipau/4be52164a69ce487dcd0673656d280da
*
* @param \Illuminate\Http\Request $request
*
* @return \Illuminate\Http\JsonResponse
*/
public function toResponse($request)
{
return $this->resource instanceof AbstractPaginator
? (new CustomPaginatedResourceResponse($this))->toResponse($request)
: parent::toResponse($request);
}
public static function collection($resource)
{
return tap(new CustomAnonymousResourceCollection($resource, static::class), function ($collection) {
if (property_exists(static::class, 'preserveKeys')) {
$collection->preserveKeys = (new static([]))->preserveKeys === true;
}
});
}
} }
+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);
+2 -10
View File
@@ -4,11 +4,9 @@ namespace App\Cron\Hourly;
use App\Contracts\Listener; use App\Contracts\Listener;
use App\Events\CronHourly; use App\Events\CronHourly;
use App\Events\PirepCancelled;
use App\Models\Enums\PirepState; use App\Models\Enums\PirepState;
use App\Models\Pirep; use App\Models\Pirep;
use Carbon\Carbon; use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
/** /**
* Remove expired live flights * Remove expired live flights
@@ -29,14 +27,8 @@ 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) Pirep::where('updated_at', '<', $date)
->where('state', PirepState::IN_PROGRESS) ->where('state', PirepState::IN_PROGRESS)
->get(); ->delete();
foreach ($pireps as $pirep) {
event(new PirepCancelled($pirep));
Log::info('Cron: Deleting Expired Live PIREP id='.$pirep->id.', state='.PirepState::label($pirep->state));
$pirep->delete();
}
} }
} }
@@ -1,9 +1,9 @@
<?php <?php
namespace App\Cron\Hourly; namespace App\Cron\Nightly;
use App\Contracts\Listener; use App\Contracts\Listener;
use App\Events\CronHourly; use App\Events\CronNightly;
use App\Services\SimBriefService; use App\Services\SimBriefService;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
@@ -22,9 +22,9 @@ class ClearExpiredSimbrief extends Listener
/** /**
* @param \App\Events\CronNightly $event * @param \App\Events\CronNightly $event
*/ */
public function handle(CronHourly $event): void public function handle(CronNightly $event): void
{ {
Log::info('Hourly: Removing expired Simbrief entries'); Log::info('Nightly: Removing expired Simbrief entries');
$this->simbriefSvc->removeExpiredEntries(); $this->simbriefSvc->removeExpiredEntries();
} }
} }
+3
View File
@@ -7,6 +7,9 @@ use App\Events\CronNightly;
use App\Services\VersionService; use App\Services\VersionService;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
/**
* Determine if any pilots should be set to ON LEAVE status
*/
class NewVersionCheck extends Listener class NewVersionCheck extends Listener
{ {
private $versionSvc; private $versionSvc;
+1 -1
View File
@@ -11,7 +11,7 @@ if (!function_exists('createFactoryICAO')) {
$characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; $characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
$max = strlen($characters) - 1; $max = strlen($characters) - 1;
$string = ''; $string = '';
for ($i = 0; $i < 5; $i++) { for ($i = 0; $i < 4; $i++) {
try { try {
$string .= $characters[random_int(0, $max)]; $string .= $characters[random_int(0, $max)];
} catch (Exception $e) { } catch (Exception $e) {
@@ -1,26 +0,0 @@
<?php
use App\Contracts\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
/**
* Increase Airport ICAO size to 5 chars
* https://github.com/nabeelio/phpvms/issues/1052
*/
class IncreaseIcaoSizes extends Migration
{
public function up()
{
Schema::table('airports', function (Blueprint $table) {
$table->string('iata', 5)->change();
$table->string('icao', 5)->change();
});
Schema::table('pireps', function (Blueprint $table) {
$table->string('dpt_airport_id', 5)->change();
$table->string('arr_airport_id', 5)->change();
$table->string('alt_airport_id', 5)->change();
});
}
}
@@ -1,19 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\DB;
class RemoveSettingSimbriefExpireDays extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
DB::table('settings')
->where(['key' => 'simbrief.expire_days'])
->delete();
}
}
@@ -1,32 +0,0 @@
<?php
use App\Contracts\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
class DiscordFields extends Migration
{
public function up()
{
// Delete the old Discord fields and then a webhook will get added
DB::table('settings')
->where(['key' => 'notifications.discord_api_key'])
->delete();
DB::table('settings')
->where(['key' => 'notifications.discord_public_channel_id'])
->delete();
DB::table('settings')
->where(['key' => 'notifications.discord_public_channel_id'])
->delete();
// Add a field to the user to enter their own Discord ID
Schema::table('users', function (Blueprint $table) {
$table->string('discord_id')
->default('')
->after('rank_id');
});
}
}
@@ -1,18 +0,0 @@
<?php
use App\Contracts\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class DiscordPrivateChannelId extends Migration
{
public function up()
{
// Add a field to the user to enter their own Discord ID
Schema::table('users', function (Blueprint $table) {
$table->string('discord_private_channel_id')
->default('')
->after('discord_id');
});
}
}
@@ -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');
});
}
}
+524 -10
View File
@@ -1,5 +1,519 @@
acars: acars:
- pirep_id: b68R5gwVzpVe - id: aM8QpMPEB15e
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
name: null
log: null
lat: '17.934117958358'
lon: '-76.77856721815'
heading: '124'
altitude: '8.1663703232199'
vs: '0'
gs: '0.0064996252497234'
transponder: null
autopilot: null
fuel_flow: null
sim_time: now
created_at: 'now'
updated_at: 'now'
- id: eZ6VJ3xj8vge
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
name: null
log: null
lat: '17.934117498661'
lon: '-76.778566516289'
heading: '124'
altitude: '8.1664622222087'
vs: '0'
gs: '0'
transponder: null
autopilot: null
fuel_flow: null
sim_time: now
created_at: 'now'
updated_at: 'now'
- id: bo2QqDLl2lLa
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
name: null
log: null
lat: '17.933884143334'
lon: '-76.778210172233'
heading: '124'
altitude: '8.1707802663933'
vs: '0'
gs: '14.419195209695'
transponder: null
autopilot: null
fuel_flow: null
sim_time: now
created_at: 'now'
updated_at: 'now'
- id: aM8QpM4qV2Be
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
name: null
log: null
lat: '17.933705349611'
lon: '-76.777936938059'
heading: '124'
altitude: '8.170089899507'
vs: '0'
gs: '15.392330039049'
transponder: null
autopilot: null
fuel_flow: null
sim_time: now
created_at: 'now'
updated_at: 'now'
- id: dR6oxR9qjoOd
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
name: null
log: null
lat: '17.933130691906'
lon: '-76.777152737985'
heading: '158'
altitude: '8.1683570286331'
vs: '0'
gs: '10.450467475023'
transponder: null
autopilot: null
fuel_flow: null
sim_time: now
created_at: 'now'
updated_at: 'now'
- id: erkRwJODRvEa
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
name: null
log: null
lat: '17.932580370289'
lon: '-76.777450200122'
heading: '221'
altitude: '8.1695896791822'
vs: '0'
gs: '12.932334300694'
transponder: null
autopilot: null
fuel_flow: null
sim_time: now
created_at: 'now'
updated_at: 'now'
- id: b2kv53VMy7Ad
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
name: null
log: null
lat: '17.932012550651'
lon: '-76.778009113329'
heading: '296'
altitude: '8.1683852467213'
vs: '0'
gs: '10.502719192825'
transponder: null
autopilot: null
fuel_flow: null
sim_time: now
created_at: 'now'
updated_at: 'now'
- id: eXDoE14JxAve
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
name: null
log: null
lat: '17.932052237309'
lon: '-76.778111495187'
heading: '290'
altitude: '8.1719753739837'
vs: '0'
gs: '12.643743277153'
transponder: null
autopilot: null
fuel_flow: null
sim_time: now
created_at: 'now'
updated_at: 'now'
- id: b68R5gZ5YyOe
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
name: null
log: null
lat: '17.932664026837'
lon: '-76.779705339967'
heading: '293'
altitude: '8.2203963962548'
vs: '0'
gs: '64.870244840054'
transponder: null
autopilot: null
fuel_flow: null
sim_time: now
created_at: 'now'
updated_at: 'now'
- id: bqxYvGNN5N0a
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
name: null
log: null
lat: '17.934300220408'
lon: '-76.783954914814'
heading: '293'
altitude: '8.3302468103811'
vs: '0'
gs: '122.78529244208'
transponder: null
autopilot: null
fuel_flow: null
sim_time: now
created_at: 'now'
updated_at: 'now'
- id: en5rpBKw514d
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
name: null
log: null
lat: '17.935736496556'
lon: '-76.78765616448'
heading: '293'
altitude: '49.554739665916'
vs: '21'
gs: '146.79677958636'
transponder: null
autopilot: null
fuel_flow: null
sim_time: now
created_at: 'now'
updated_at: 'now'
- id: erkRwJA29l2a
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
name: null
log: null
lat: '17.976972983585'
lon: '-76.896548114872'
heading: '297'
altitude: '6228.684012199'
vs: '62'
gs: '281.03976876098'
transponder: null
autopilot: null
fuel_flow: null
sim_time: now
created_at: 'now'
updated_at: 'now'
- id: dR6oxR3r5nwd
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
name: null
log: null
lat: '18.061360208405'
lon: '-77.056156629983'
heading: '301'
altitude: '12522.331716891'
vs: '25'
gs: '371.70833265547'
transponder: null
autopilot: null
fuel_flow: null
sim_time: now
created_at: 'now'
updated_at: 'now'
- id: e1wr82J877Zb
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
name: null
log: null
lat: '18.17373613295'
lon: '-77.260347185993'
heading: '301'
altitude: '16802.15636323'
vs: '43'
gs: '421.37353688139'
transponder: null
autopilot: null
fuel_flow: null
sim_time: now
created_at: 'now'
updated_at: 'now'
- id: bqxYvGyExN2a
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
name: null
log: null
lat: '18.193907285814'
lon: '-77.29810465405'
heading: '297'
altitude: '17395.953175647'
vs: '40'
gs: '425.98105291451'
transponder: null
autopilot: null
fuel_flow: null
sim_time: now
created_at: 'now'
updated_at: 'now'
- id: aQW0wQDQk5Md
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
name: null
log: null
lat: '18.648921231143'
lon: '-78.014696613517'
heading: '323'
altitude: '37108.124381987'
vs: '22'
gs: '438.52028383384'
transponder: null
autopilot: null
fuel_flow: null
sim_time: now
created_at: 'now'
updated_at: 'now'
- id: e9rQ5lk3p63a
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
name: null
log: null
lat: '18.796585259338'
lon: '-78.194734005052'
heading: '260'
altitude: '39718.178225504'
vs: '19'
gs: '432.41969107334'
transponder: null
autopilot: null
fuel_flow: null
sim_time: now
created_at: 'now'
updated_at: 'now'
- id: aQW0wQP8vZqd
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
name: null
log: null
lat: '18.660552760063'
lon: '-78.407597067994'
heading: '242'
altitude: '40998.775690971'
vs: '-25'
gs: '449.51695639627'
transponder: null
autopilot: null
fuel_flow: null
sim_time: now
created_at: 'now'
updated_at: 'now'
- id: bqxYvGKgp32a
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
name: null
log: null
lat: '18.592775999582'
lon: '-78.638711340118'
heading: '298'
altitude: '41060.297106821'
vs: '0'
gs: '427.14806185954'
transponder: null
autopilot: null
fuel_flow: null
sim_time: now
created_at: 'now'
updated_at: 'now'
- id: bqxYvGg2r02a
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
name: null
log: null
lat: '18.718367591656'
lon: '-78.840980459275'
heading: '284'
altitude: '41065.55293844'
vs: '1'
gs: '424.89060056552'
transponder: null
autopilot: null
fuel_flow: null
sim_time: now
created_at: 'now'
updated_at: 'now'
- id: e0RV61wPj53b
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
name: null
log: null
lat: '18.77448809677'
lon: '-79.082727467209'
heading: '283'
altitude: '41069.809333539'
vs: '0'
gs: '425.02780492483'
transponder: null
autopilot: null
fuel_flow: null
sim_time: now
created_at: 'now'
updated_at: 'now'
- id: dwpmBOo3wWwe
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
name: null
log: null
lat: '18.813031600863'
lon: '-79.249543355636'
heading: '283'
altitude: '41072.545805172'
vs: '0'
gs: '425.04687332464'
transponder: null
autopilot: null
fuel_flow: null
sim_time: now
created_at: 'now'
updated_at: 'now'
- id: ejRqlxXoZPle
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
name: null
log: null
lat: '18.840653974635'
lon: '-79.370042672541'
heading: '283'
altitude: '40396.200981621'
vs: '-16'
gs: '428.08364925851'
transponder: null
autopilot: null
fuel_flow: null
sim_time: now
created_at: 'now'
updated_at: 'now'
- id: eVOPBYw4q9Xa
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
name: null
log: null
lat: '18.868358744495'
lon: '-79.491434926253'
heading: '283'
altitude: '39399.093383161'
vs: '-16'
gs: '427.57826037174'
transponder: null
autopilot: null
fuel_flow: null
sim_time: now
created_at: 'now'
updated_at: 'now'
- id: aOYyrOmVPzEd
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
name: null
log: null
lat: '18.896191929474'
lon: '-79.613169477385'
heading: '284'
altitude: '36491.730092364'
vs: '-55'
gs: '429.74732238829'
transponder: null
autopilot: null
fuel_flow: null
sim_time: now
created_at: 'now'
updated_at: 'now'
- id: dL98oLQgyzje
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
name: null
log: null
lat: '18.9242378342'
lon: '-79.736368411294'
heading: '284'
altitude: '32998.644142986'
vs: '-61'
gs: '434.90864533098'
transponder: null
autopilot: null
fuel_flow: null
sim_time: now
created_at: 'now'
updated_at: 'now'
- id: e9rQ5lqD2o8a
pirep_id: b68R5gwVzpVe
type: '0'
nav_type: null
order: '0'
name: null
log: null
lat: '18.952608029755'
lon: '-79.861339775352'
heading: '284'
altitude: '29069.168636089'
vs: '-68'
gs: '441.90475491564'
transponder: null
autopilot: null
fuel_flow: null
sim_time: now
created_at: 'now'
updated_at: 'now'
- id: av2oANWY1vma
pirep_id: b68R5gwVzpVe
type: '0' type: '0'
nav_type: null nav_type: null
order: '0' order: '0'
@@ -36,7 +550,7 @@ acars:
sim_time: now sim_time: now
created_at: 'now' created_at: 'now'
updated_at: 'now' updated_at: 'now'
- id: 9aAN4mxlK9zb1 - id: e1wr82gp8zGb
pirep_id: b68R5gwVzpVe pirep_id: b68R5gwVzpVe
type: '0' type: '0'
nav_type: null nav_type: null
@@ -55,7 +569,7 @@ acars:
sim_time: now sim_time: now
created_at: 'now' created_at: 'now'
updated_at: 'now' updated_at: 'now'
- id: 9aAN4mxlK9zb2 - id: dG65jDL2gK0b
pirep_id: b68R5gwVzpVe pirep_id: b68R5gwVzpVe
type: '0' type: '0'
nav_type: null nav_type: null
@@ -74,7 +588,7 @@ acars:
sim_time: now sim_time: now
created_at: 'now' created_at: 'now'
updated_at: 'now' updated_at: 'now'
- id: 9aAN4mxlK9zb3 - id: epYQ0ENmyvXa
pirep_id: b68R5gwVzpVe pirep_id: b68R5gwVzpVe
type: '0' type: '0'
nav_type: null nav_type: null
@@ -93,7 +607,7 @@ acars:
sim_time: now sim_time: now
created_at: 'now' created_at: 'now'
updated_at: 'now' updated_at: 'now'
- id: 9aAN4mxlK9zb34 - id: erkRwJPrVoEa
pirep_id: b68R5gwVzpVe pirep_id: b68R5gwVzpVe
type: '0' type: '0'
nav_type: null nav_type: null
@@ -112,7 +626,7 @@ acars:
sim_time: now sim_time: now
created_at: 'now' created_at: 'now'
updated_at: 'now' updated_at: 'now'
- id: 9aAN4mxlK9zb35 - id: e1wr82gZXqZb
pirep_id: b68R5gwVzpVe pirep_id: b68R5gwVzpVe
type: '0' type: '0'
nav_type: null nav_type: null
@@ -131,7 +645,7 @@ acars:
sim_time: now sim_time: now
created_at: 'now' created_at: 'now'
updated_at: 'now' updated_at: 'now'
- id: 9aAN4mxlK9zb36 - id: eER95AJ4XLga
pirep_id: b68R5gwVzpVe pirep_id: b68R5gwVzpVe
type: '0' type: '0'
nav_type: null nav_type: null
@@ -150,7 +664,7 @@ acars:
sim_time: now sim_time: now
created_at: 'now' created_at: 'now'
updated_at: 'now' updated_at: 'now'
- id: 9aAN4mxlK9zb37 - id: dPNZvP0O0Gza
pirep_id: b68R5gwVzpVe pirep_id: b68R5gwVzpVe
type: '0' type: '0'
nav_type: null nav_type: null
@@ -169,7 +683,7 @@ acars:
sim_time: now sim_time: now
created_at: 'now' created_at: 'now'
updated_at: 'now' updated_at: 'now'
- id: 9aAN4mxlK9zb38 - id: aQW0wQYVm2Yd
pirep_id: b68R5gwVzpVe pirep_id: b68R5gwVzpVe
type: '0' type: '0'
nav_type: null nav_type: null
@@ -188,7 +702,7 @@ acars:
sim_time: now sim_time: now
created_at: 'now' created_at: 'now'
updated_at: 'now' updated_at: 'now'
- id: 9aAN4mxlK9zb39 - id: eXDoE11x32We
pirep_id: b68R5gwVzpVe pirep_id: b68R5gwVzpVe
type: '0' type: '0'
nav_type: null nav_type: null
-26
View File
@@ -34,17 +34,6 @@ airports:
lon: -97.6698889 lon: -97.6698889
hub: 1 hub: 1
ground_handling_cost: 100 ground_handling_cost: 100
- id: KPHN
iata: HPN
icao: KPHN
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: KJFK - id: KJFK
iata: JFK iata: JFK
icao: KJFK icao: KJFK
@@ -459,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
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
+12 -54
View File
@@ -54,13 +54,6 @@
options: '' options: ''
type: text type: text
description: 'Enter your Google Analytics Tracking ID' description: 'Enter your Google Analytics Tracking ID'
- key: general.record_user_ip
name: 'Record user IP address'
group: general
value: true
options: ''
type: boolean
description: Record the user's IP address on register/login
- key: units.currency - key: units.currency
name: 'Currency' name: 'Currency'
group: units group: units
@@ -137,13 +130,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
@@ -158,20 +144,6 @@
options: options:
type: text type: text
description: If an airport's Jet A Fuel Cost isn't added, set this value by default description: If an airport's Jet A Fuel Cost isn't added, set this value by default
- key: airports.default_100ll_fuel_cost
name: 'Default 100LL Fuel Cost'
group: airports
value: 0.9
options:
type: text
description: If an airport's 100LL Fuel Cost isn't added, set this value by default
- key: airports.default_mogas_fuel_cost
name: 'Default MOGAS Fuel Cost'
group: airports
value: 0.8
options:
type: text
description: If an airport's MOGAS Fuel Cost isn't added, set this value by default
- key: bids.disable_flight_on_bid - key: bids.disable_flight_on_bid
name: 'Disable flight on bid' name: 'Disable flight on bid'
group: bids group: bids
@@ -221,13 +193,13 @@
options: '' options: ''
type: boolean type: boolean
description: 'Only allow briefs to be created for bidded flights' description: 'Only allow briefs to be created for bidded flights'
- key: simbrief.expire_hours - key: simbrief.expire_days
name: 'Simbrief Expire Time' name: 'Simbrief Expire Time'
group: simbrief group: simbrief
value: 6 value: 5
options: '' options: ''
type: number type: number
description: 'Hours after how long to remove unused briefs' description: 'Days after how long to remove unused briefs'
- key: simbrief.noncharter_pax_weight - key: simbrief.noncharter_pax_weight
name: 'Non-Charter Passenger Weight' name: 'Non-Charter Passenger Weight'
group: simbrief group: simbrief
@@ -270,13 +242,6 @@
options: '' options: ''
type: boolean type: boolean
description: 'Use privatized user name as SimBrief OFP captain name' description: 'Use privatized user name as SimBrief OFP captain name'
- key: simbrief.block_aircraft
name: 'Restrict Aircraft'
group: simbrief
value: false
options: ''
type: boolean
description: 'When enabled, an aircraft can only be used for one active SimBrief OFP and Flight/Pirep'
- key: pireps.duplicate_check_time - key: pireps.duplicate_check_time
name: 'PIREP duplicate time check' name: 'PIREP duplicate time check'
group: pireps group: pireps
@@ -290,14 +255,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
@@ -389,20 +347,20 @@
options: '' options: ''
type: boolean type: boolean
description: 'Count transfer hours in calculations, like ranks and the total hours' description: 'Count transfer hours in calculations, like ranks and the total hours'
- key: notifications.discord_public_webhook_url - key: notifications.discord_api_key
name: Discord Public Webhook URL name: Discord API token
group: notifications group: notifications
value: '' value: ''
options: '' options: ''
type: text type: text
description: The Discord Webhook URL for public notifications description: Discord API token for notifications
- key: notifications.discord_private_webhook_url - key: 'notifications.discord_public_channel_id'
name: Discord Private Webhook URL name: 'Discord Public Channel ID'
group: notifications group: 'notifications'
value: '' value: ''
options: '' options: ''
type: text type: 'text'
description: The Discord Webhook URL for private notifications description: 'Discord public channel ID for broadcasat notifications'
- key: 'cron.random_id' - key: 'cron.random_id'
name: 'Cron Randomized ID' name: 'Cron Randomized ID'
group: 'cron' group: 'cron'
-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;
}
}
-16
View File
@@ -1,16 +0,0 @@
<?php
namespace App\Events;
use App\Contracts\Event;
use App\Models\Pirep;
class PirepStateChange extends Event
{
public $pirep;
public function __construct(Pirep $pirep)
{
$this->pirep = $pirep;
}
}
-19
View File
@@ -1,19 +0,0 @@
<?php
namespace App\Events;
use App\Contracts\Event;
use App\Models\Pirep;
/**
* Status change like Boarding, Taxi, etc
*/
class PirepStatusChange extends Event
{
public $pirep;
public function __construct(Pirep $pirep)
{
$this->pirep = $pirep;
}
}
-38
View File
@@ -1,38 +0,0 @@
<?php
namespace App\Exceptions;
use App\Models\Aircraft;
class AircraftNotAvailable extends AbstractHttpException
{
public const MESSAGE = 'The aircraft is not available for flight';
private $aircraft;
public function __construct(Aircraft $aircraft)
{
$this->aircraft = $aircraft;
parent::__construct(
400,
static::MESSAGE
);
}
public function getErrorType(): string
{
return 'aircraft-not-available';
}
public function getErrorDetails(): string
{
return $this->getMessage();
}
public function getErrorMetadata(): array
{
return [
'aircraft_id' => $this->aircraft->id,
];
}
}
-44
View File
@@ -1,44 +0,0 @@
<?php
namespace App\Exceptions;
use App\Models\Pirep;
class PirepError extends AbstractHttpException
{
private $pirep;
private $error;
public function __construct(Pirep $pirep, string $error)
{
$this->error = $error;
$this->pirep = $pirep;
parent::__construct(400, $error);
}
/**
* Return the RFC 7807 error type (without the URL root)
*/
public function getErrorType(): string
{
return 'pirep-error';
}
/**
* Get the detailed error string
*/
public function getErrorDetails(): string
{
return $this->getMessage();
}
/**
* Return an array with the error details, merged with the RFC7807 response
*/
public function getErrorMetadata(): array
{
return [
'pirep_id' => $this->pirep->id,
];
}
}
@@ -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),
]); ]);
@@ -152,7 +152,7 @@ class FlightController extends Controller
{ {
return view('admin.flights.create', [ return view('admin.flights.create', [
'flight' => null, 'flight' => null,
'days' => 0, 'days' => [],
'flight_fields' => $this->flightFieldRepo->all(), 'flight_fields' => $this->flightFieldRepo->all(),
'airlines' => $this->airlineRepo->selectBoxList(), 'airlines' => $this->airlineRepo->selectBoxList(),
'airports' => $this->airportRepo->selectBoxList(true, false), 'airports' => $this->airportRepo->selectBoxList(true, false),
@@ -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)->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);
} }
/** /**
@@ -7,24 +7,29 @@ use App\Repositories\KvpRepository;
use App\Services\CronService; use App\Services\CronService;
use App\Services\VersionService; use App\Services\VersionService;
use App\Support\Utils; use App\Support\Utils;
use Codedge\Updater\UpdaterManager;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Artisan; use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use Laracasts\Flash\Flash; use Laracasts\Flash\Flash;
use Nwidart\Modules\Facades\Module;
class MaintenanceController extends Controller class MaintenanceController extends Controller
{ {
private $cronSvc; private $cronSvc;
private $kvpRepo; private $kvpRepo;
private $updateManager;
private $versionSvc; private $versionSvc;
public function __construct( public function __construct(
CronService $cronSvc, CronService $cronSvc,
KvpRepository $kvpRepo, KvpRepository $kvpRepo,
UpdaterManager $updateManager,
VersionService $versionSvc VersionService $versionSvc
) { ) {
$this->cronSvc = $cronSvc; $this->cronSvc = $cronSvc;
$this->kvpRepo = $kvpRepo; $this->kvpRepo = $kvpRepo;
$this->updateManager = $updateManager;
$this->versionSvc = $versionSvc; $this->versionSvc = $versionSvc;
} }
@@ -101,6 +106,24 @@ class MaintenanceController extends Controller
return redirect(route('admin.maintenance.index')); return redirect(route('admin.maintenance.index'));
} }
/**
* Update the phpVMS install
*
* @param \Illuminate\Http\Request $request
*
* @return mixed
*/
public function update(Request $request)
{
$new_version_tag = $this->kvpRepo->get('latest_version_tag');
Log::info('Attempting to update to '.$new_version_tag);
$module = Module::find('updater');
$module->enable();
return redirect('/update/downloader');
}
/** /**
* Enable the cron, or if it's enabled, change the ID that is used * Enable the cron, or if it's enabled, change the ID that is used
* *
@@ -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;
@@ -101,7 +100,7 @@ class PirepController extends Controller
$tmp[$ac->id] = $ac['name'].' - '.$ac['registration']; $tmp[$ac->id] = $ac['name'].' - '.$ac['registration'];
} }
$aircraft[$subfleet->type] = $tmp; $aircraft[$subfleet->name] = $tmp;
} }
return $aircraft; return $aircraft;
@@ -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);
+117 -195
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;
} }
/** /**
@@ -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,168 +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->all();
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.');
// Cache::forget(config('cache.keys.RANKS_PILOT_LIST.key'));
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);
}
}
+17 -101
View File
@@ -6,13 +6,12 @@ use App\Contracts\Controller;
use App\Http\Requests\CreateUserRequest; use App\Http\Requests\CreateUserRequest;
use App\Http\Requests\UpdateUserRequest; use App\Http\Requests\UpdateUserRequest;
use App\Models\Rank; use App\Models\Rank;
use App\Models\Role;
use App\Models\User; use App\Models\User;
use App\Models\UserAward; use App\Models\UserAward;
use App\Repositories\AirlineRepository; 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\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;
@@ -30,36 +29,28 @@ class UserController extends Controller
private $airlineRepo; private $airlineRepo;
private $airportRepo; private $airportRepo;
private $pirepRepo; private $pirepRepo;
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 UserRepository $userRepo
* @param TypeRatingRepository $typeratingRepo * @param UserService $userSvc
* @param UserRepository $userRepo
* @param UserService $userSvc
*/ */
public function __construct( public function __construct(
AirlineRepository $airlineRepo, AirlineRepository $airlineRepo,
AirportRepository $airportRepo, AirportRepository $airportRepo,
PirepRepository $pirepRepo, PirepRepository $pirepRepo,
RoleRepository $roleRepo,
TypeRatingRepository $typeratingRepo,
UserRepository $userRepo, UserRepository $userRepo,
UserService $userSvc UserService $userSvc
) { ) {
$this->airlineRepo = $airlineRepo; $this->airlineRepo = $airlineRepo;
$this->airportRepo = $airportRepo; $this->airportRepo = $airportRepo;
$this->pirepRepo = $pirepRepo; $this->pirepRepo = $pirepRepo;
$this->roleRepo = $roleRepo;
$this->typeratingRepo = $typeratingRepo;
$this->userSvc = $userSvc; $this->userSvc = $userSvc;
$this->userRepo = $userRepo; $this->userRepo = $userRepo;
} }
@@ -97,7 +88,6 @@ class UserController extends Controller
->mapWithKeys(function ($item, $key) { ->mapWithKeys(function ($item, $key) {
return [strtolower($item['alpha2']) => $item['name']]; return [strtolower($item['alpha2']) => $item['name']];
}); });
$roles = $this->roleRepo->selectBoxList(false, true);
return view('admin.users.create', [ return view('admin.users.create', [
'user' => null, 'user' => null,
@@ -108,7 +98,7 @@ class UserController extends Controller
'countries' => $countries, 'countries' => $countries,
'airports' => $airports, 'airports' => $airports,
'ranks' => Rank::all()->pluck('name', 'id'), 'ranks' => Rank::all()->pluck('name', 'id'),
'roles' => $roles, 'roles' => Role::all()->pluck('name', 'id'),
]); ]);
} }
@@ -154,7 +144,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)) {
@@ -173,20 +163,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);
$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' => Role::all()->pluck('name', 'id'),
'avail_ratings' => $avail_ratings,
]); ]);
} }
@@ -267,7 +254,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 +277,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 +305,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');
@@ -16,8 +16,9 @@ class AirlineController extends Controller
* *
* @param AirlineRepository $airlineRepo * @param AirlineRepository $airlineRepo
*/ */
public function __construct(AirlineRepository $airlineRepo) public function __construct(
{ AirlineRepository $airlineRepo
) {
$this->airlineRepo = $airlineRepo; $this->airlineRepo = $airlineRepo;
} }
@@ -30,9 +31,11 @@ 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', 'asc')
->paginate();
return AirlineResource::collection($airlines); return AirlineResource::collection($airports);
} }
/** /**
+35 -38
View File
@@ -23,11 +23,10 @@ use App\Models\Enums\PirepFieldSource;
use App\Models\Enums\PirepSource; use App\Models\Enums\PirepSource;
use App\Models\Pirep; use App\Models\Pirep;
use App\Models\PirepComment; use App\Models\PirepComment;
use App\Models\PirepFare; use App\Repositories\AcarsRepository;
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\FareService;
use App\Services\Finance\PirepFinanceService; use App\Services\Finance\PirepFinanceService;
use App\Services\PirepService; use App\Services\PirepService;
use App\Services\UserService; use App\Services\UserService;
@@ -38,6 +37,8 @@ use Illuminate\Support\Facades\Log;
class PirepController extends Controller class PirepController extends Controller
{ {
private $acarsRepo;
private $fareSvc;
private $financeSvc; private $financeSvc;
private $journalRepo; private $journalRepo;
private $pirepRepo; private $pirepRepo;
@@ -45,6 +46,8 @@ class PirepController extends Controller
private $userSvc; private $userSvc;
/** /**
* @param AcarsRepository $acarsRepo
* @param FareService $fareSvc
* @param PirepFinanceService $financeSvc * @param PirepFinanceService $financeSvc
* @param JournalRepository $journalRepo * @param JournalRepository $journalRepo
* @param PirepRepository $pirepRepo * @param PirepRepository $pirepRepo
@@ -52,12 +55,16 @@ class PirepController extends Controller
* @param UserService $userSvc * @param UserService $userSvc
*/ */
public function __construct( public function __construct(
AcarsRepository $acarsRepo,
FareService $fareSvc,
PirepFinanceService $financeSvc, PirepFinanceService $financeSvc,
JournalRepository $journalRepo, JournalRepository $journalRepo,
PirepRepository $pirepRepo, PirepRepository $pirepRepo,
PirepService $pirepSvc, PirepService $pirepSvc,
UserService $userSvc UserService $userSvc
) { ) {
$this->acarsRepo = $acarsRepo;
$this->fareSvc = $fareSvc;
$this->financeSvc = $financeSvc; $this->financeSvc = $financeSvc;
$this->journalRepo = $journalRepo; $this->journalRepo = $journalRepo;
$this->pirepRepo = $pirepRepo; $this->pirepRepo = $pirepRepo;
@@ -94,7 +101,7 @@ class PirepController extends Controller
/** /**
* Check if a PIREP is cancelled * Check if a PIREP is cancelled
* *
* @param Pirep $pirep * @param $pirep
* *
* @throws \App\Exceptions\PirepCancelled * @throws \App\Exceptions\PirepCancelled
*/ */
@@ -106,52 +113,50 @@ class PirepController extends Controller
} }
/** /**
* @param $pirep
* @param Request $request * @param Request $request
*
* @return PirepFieldValue[]
*/ */
protected function getFields(Request $request): ?array protected function updateFields($pirep, Request $request)
{ {
if (!$request->filled('fields')) { if (!$request->filled('fields')) {
return []; return;
} }
$pirep_fields = []; $pirep_fields = [];
foreach ($request->input('fields') as $field_name => $field_value) { foreach ($request->input('fields') as $field_name => $field_value) {
$pirep_fields[] = new PirepFieldValue([ $pirep_fields[] = [
'name' => $field_name, 'name' => $field_name,
'value' => $field_value, 'value' => $field_value,
'source' => PirepFieldSource::ACARS, 'source' => PirepFieldSource::ACARS,
]); ];
} }
return $pirep_fields; $this->pirepSvc->updateCustomFields($pirep->id, $pirep_fields);
} }
/** /**
* Save the fares * Save the fares
* *
* @param $pirep
* @param Request $request * @param Request $request
* *
* @throws \Exception * @throws \Exception
*
* @return PirepFare[]
*/ */
protected function getFares(Request $request): ?array protected function updateFares($pirep, Request $request)
{ {
if (!$request->filled('fares')) { if (!$request->filled('fares')) {
return []; return;
} }
$fares = []; $fares = [];
foreach ($request->post('fares') as $fare) { foreach ($request->post('fares') as $fare) {
$fares[] = new PirepFare([ $fares[] = [
'fare_id' => $fare['id'], 'fare_id' => $fare['id'],
'count' => $fare['count'], 'count' => $fare['count'],
]); ];
} }
return $fares; $this->fareSvc->saveForPirep($pirep, $fares);
} }
/** /**
@@ -168,7 +173,6 @@ class PirepController extends Controller
'comments', 'comments',
'flight', 'flight',
'simbrief', 'simbrief',
'position',
'user', 'user',
]; ];
@@ -206,13 +210,14 @@ class PirepController extends Controller
$attrs = $this->parsePirep($request); $attrs = $this->parsePirep($request);
$attrs['source'] = PirepSource::ACARS; $attrs['source'] = PirepSource::ACARS;
$fields = $this->getFields($request); $pirep = $this->pirepSvc->prefile($user, $attrs);
$fares = $this->getFares($request);
$pirep = $this->pirepSvc->prefile($user, $attrs, $fields, $fares);
Log::info('PIREP PREFILED'); Log::info('PIREP PREFILED');
Log::info($pirep->id); Log::info($pirep->id);
$this->updateFields($pirep, $request);
$this->updateFares($pirep, $request);
return $this->get($pirep->id); return $this->get($pirep->id);
} }
@@ -236,12 +241,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);
@@ -257,9 +258,9 @@ class PirepController extends Controller
} }
} }
$fields = $this->getFields($request); $pirep = $this->pirepRepo->update($attrs, $pirep_id);
$fares = $this->getFares($request); $this->updateFields($pirep, $request);
$pirep = $this->pirepSvc->update($pirep_id, $attrs, $fields, $fares); $this->updateFares($pirep, $request);
event(new PirepUpdated($pirep)); event(new PirepUpdated($pirep));
@@ -283,7 +284,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...
@@ -303,13 +303,11 @@ class PirepController extends Controller
} }
try { try {
$fields = $this->getFields($request); $pirep = $this->pirepSvc->file($pirep, $attrs);
$fares = $this->getFares($request); $this->updateFields($pirep, $request);
$pirep = $this->pirepSvc->file($pirep, $attrs, $fields, $fares); $this->updateFares($pirep, $request);
} catch (\Exception $e) { } catch (\Exception $e) {
Log::error($e); Log::error($e);
throw $e;
} }
// See if there there is any route data posted // See if there there is any route data posted
@@ -338,7 +336,7 @@ class PirepController extends Controller
*/ */
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);
$this->pirepSvc->cancel($pirep); $this->pirepSvc->cancel($pirep);
@@ -411,8 +409,7 @@ class PirepController extends Controller
$pirep = Pirep::find($pirep_id); $pirep = Pirep::find($pirep_id);
$this->checkCancelled($pirep); $this->checkCancelled($pirep);
$fields = $this->getFields($request); $this->updateFields($pirep, $request);
$this->pirepSvc->updateCustomFields($pirep_id, $fields);
return new PirepFieldCollection($pirep->fields); return new PirepFieldCollection($pirep->fields);
} }
@@ -3,7 +3,6 @@
namespace App\Http\Controllers\Api; namespace App\Http\Controllers\Api;
use App\Contracts\Controller; use App\Contracts\Controller;
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;
@@ -145,28 +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->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
* *
@@ -5,7 +5,6 @@ namespace App\Http\Controllers\Auth;
use App\Contracts\Controller; use App\Contracts\Controller;
use App\Exceptions\PilotIdNotFound; use App\Exceptions\PilotIdNotFound;
use App\Models\Enums\UserState; use App\Models\Enums\UserState;
use App\Models\User;
use App\Services\UserService; use App\Services\UserService;
use Illuminate\Foundation\Auth\AuthenticatesUsers; use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request; use Illuminate\Http\Request;
@@ -105,16 +104,14 @@ class LoginController extends Controller
*/ */
protected function sendLoginResponse(Request $request) protected function sendLoginResponse(Request $request)
{ {
/** @var User $user */
$user = Auth::user(); $user = Auth::user();
if (setting('general.record_user_ip', true)) { $user->last_ip = $request->ip();
$user->last_ip = $request->ip(); $user->save();
$user->save();
}
if ($user->state !== UserState::ACTIVE && $user->state !== UserState::ON_LEAVE) { if ($user->state !== UserState::ACTIVE && $user->state !== UserState::ON_LEAVE) {
Log::info('Trying to login '.$user->ident.', state '.UserState::label($user->state)); Log::info('Trying to login '.$user->ident.', state '
.UserState::label($user->state));
// Log them out // Log them out
$this->guard()->logout(); $this->guard()->logout();
@@ -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,
@@ -119,16 +119,11 @@ class RegisterController extends Controller
* *
* @return User * @return User
*/ */
protected function create(Request $request): User protected function create(array $opts)
{ {
// Default options // Default options
$opts = $request->all();
$opts['password'] = Hash::make($opts['password']); $opts['password'] = Hash::make($opts['password']);
if (setting('general.record_user_ip', true)) {
$opts['last_ip'] = $request->ip();
}
// Convert transfer hours into minutes // Convert transfer hours into minutes
if (isset($opts['transfer_time'])) { if (isset($opts['transfer_time'])) {
$opts['transfer_time'] *= 60; $opts['transfer_time'] *= 60;
@@ -138,7 +133,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([
@@ -163,7 +158,7 @@ class RegisterController extends Controller
{ {
$this->validator($request->all())->validate(); $this->validator($request->all())->validate();
$user = $this->create($request); $user = $this->create($request->all());
if ($user->state === UserState::PENDING) { if ($user->state === UserState::PENDING) {
return view('auth.pending'); return view('auth.pending');
} }
@@ -35,26 +35,23 @@ 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->find($id);
if (!$airport) { if (empty($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,
])->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,
])->all(); ])->all();
return view('airports.show', [ return view('airports.show', [
@@ -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);
@@ -5,7 +5,6 @@ namespace App\Http\Controllers\Frontend;
use App\Contracts\Controller; use App\Contracts\Controller;
use App\Models\Bid; use App\Models\Bid;
use App\Models\Enums\FlightType; use App\Models\Enums\FlightType;
use App\Models\Flight;
use App\Repositories\AirlineRepository; use App\Repositories\AirlineRepository;
use App\Repositories\AirportRepository; use App\Repositories\AirportRepository;
use App\Repositories\Criteria\WhereCriteria; use App\Repositories\Criteria\WhereCriteria;
@@ -13,7 +12,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 +24,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 +33,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 +41,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 +48,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 +82,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;
@@ -112,44 +105,20 @@ class FlightController extends Controller
Log::emergency($e); Log::emergency($e);
} }
// Get only used Flight Types for the search form
// And filter according to settings
$usedtypes = Flight::select('flight_type')
->where($where)
->groupby('flight_type')
->orderby('flight_type')
->get();
// Build collection with type codes and labels
$flight_types = collect('', '');
foreach ($usedtypes as $ftype) {
$flight_types->put($ftype->flight_type, FlightType::label($ftype->flight_type));
}
$flights = $this->flightRepo->searchCriteria($request) $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,
@@ -159,14 +128,13 @@ class FlightController extends Controller
'saved' => $saved_flights, 'saved' => $saved_flights,
'subfleets' => $this->subfleetRepo->selectBoxList(true), 'subfleets' => $this->subfleetRepo->selectBoxList(true),
'flight_number' => $request->input('flight_number'), 'flight_number' => $request->input('flight_number'),
'flight_types' => $flight_types, 'flight_types' => FlightType::select(true),
'flight_type' => $request->input('flight_type'), 'flight_type' => $request->input('flight_type'),
'arr_icao' => $request->input('arr_icao'), 'arr_icao' => $request->input('arr_icao'),
'dep_icao' => $request->input('dep_icao'), 'dep_icao' => $request->input('dep_icao'),
'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 +161,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 +173,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 +185,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 +193,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'),
]); ]);
} }
} }
@@ -3,7 +3,6 @@
namespace App\Http\Controllers\Frontend; namespace App\Http\Controllers\Frontend;
use App\Contracts\Controller; use App\Contracts\Controller;
use App\Models\Enums\UserState;
use App\Models\User; use App\Models\User;
use Illuminate\Database\QueryException; use Illuminate\Database\QueryException;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
@@ -16,7 +15,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::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', [
@@ -9,7 +9,6 @@ use App\Models\Enums\PirepSource;
use App\Models\Enums\PirepState; use App\Models\Enums\PirepState;
use App\Models\Fare; use App\Models\Fare;
use App\Models\Pirep; use App\Models\Pirep;
use App\Models\PirepFare;
use App\Models\SimBrief; use App\Models\SimBrief;
use App\Models\User; use App\Models\User;
use App\Repositories\AircraftRepository; use App\Repositories\AircraftRepository;
@@ -91,12 +90,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,13 +99,11 @@ 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'];
} }
$aircraft[$subfleet->type] = $tmp; $aircraft[$subfleet->name] = $tmp;
} }
return $aircraft; return $aircraft;
@@ -119,18 +112,19 @@ class PirepController extends Controller
/** /**
* Save any custom fields found * Save any custom fields found
* *
* @param Pirep $pirep
* @param Request $request * @param Request $request
*/ */
protected function saveCustomFields(Request $request): array protected function saveCustomFields(Pirep $pirep, Request $request)
{ {
$fields = []; $custom_fields = [];
$pirep_fields = $this->pirepFieldRepo->all(); $pirep_fields = $this->pirepFieldRepo->all();
foreach ($pirep_fields as $field) { foreach ($pirep_fields as $field) {
if (!$request->filled($field->slug)) { if (!$request->filled($field->slug)) {
continue; continue;
} }
$fields[] = [ $custom_fields[] = [
'name' => $field->name, 'name' => $field->name,
'slug' => $field->slug, 'slug' => $field->slug,
'value' => $request->input($field->slug), 'value' => $request->input($field->slug),
@@ -138,9 +132,8 @@ class PirepController extends Controller
]; ];
} }
Log::info('PIREP Custom Fields', $fields); Log::info('PIREP Custom Fields', $custom_fields);
$this->pirepSvc->updateCustomFields($pirep->id, $custom_fields);
return $fields;
} }
/** /**
@@ -166,10 +159,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);
@@ -188,7 +181,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 +200,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'));
@@ -409,8 +389,8 @@ class PirepController extends Controller
$attrs['submitted_at'] = Carbon::now('UTC'); $attrs['submitted_at'] = Carbon::now('UTC');
$pirep->submitted_at = Carbon::now('UTC'); $pirep->submitted_at = Carbon::now('UTC');
$fields = $this->saveCustomFields($request); $pirep = $this->pirepSvc->create($pirep);
$pirep = $this->pirepSvc->create($pirep, $fields); $this->saveCustomFields($pirep, $request);
$this->saveFares($pirep, $request); $this->saveFares($pirep, $request);
$this->pirepSvc->saveRoute($pirep); $this->pirepSvc->saveRoute($pirep);
@@ -419,13 +399,7 @@ class PirepController extends Controller
if ($brief !== null) { if ($brief !== null) {
/** @var SimBriefService $sbSvc */ /** @var SimBriefService $sbSvc */
$sbSvc = app(SimBriefService::class); $sbSvc = app(SimBriefService::class);
// Keep the flight_id with SimBrief depending on the button selected $sbSvc->attachSimbriefToPirep($pirep, $brief);
// Save = Keep the flight_id , Submit = Remove the flight_id
if ($attrs['submit'] === 'save') {
$sbSvc->attachSimbriefToPirep($pirep, $brief, true);
} elseif ($attrs['submit'] === 'submit') {
$sbSvc->attachSimbriefToPirep($pirep, $brief);
}
} }
} }
@@ -551,8 +525,7 @@ class PirepController extends Controller
$this->pirepSvc->saveRoute($pirep); $this->pirepSvc->saveRoute($pirep);
} }
$fields = $this->saveCustomFields($request); $this->saveCustomFields($pirep, $request);
$this->pirepSvc->updateCustomFields($pirep->id, $fields);
$this->saveFares($pirep, $request); $this->saveFares($pirep, $request);
if ($attrs['submit'] === 'save') { if ($attrs['submit'] === 'save') {
@@ -10,7 +10,6 @@ use App\Repositories\AirlineRepository;
use App\Repositories\AirportRepository; use App\Repositories\AirportRepository;
use App\Repositories\UserRepository; use App\Repositories\UserRepository;
use App\Support\Countries; use App\Support\Countries;
use App\Support\Discord;
use App\Support\Timezonelist; use App\Support\Timezonelist;
use App\Support\Utils; use App\Support\Utils;
use Illuminate\Http\Request; use Illuminate\Http\Request;
@@ -80,19 +79,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 +111,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 +122,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,
@@ -177,16 +181,6 @@ class ProfileController extends Controller
Storage::delete($user->avatar); Storage::delete($user->avatar);
} }
// Find out the user's private channel id
/*
// TODO: Uncomment when Discord API functionality is enabled
if ($request->filled('discord_id')) {
$discord_id = $request->post('discord_id');
if ($discord_id !== $user->discord_id) {
$req_data['discord_private_channel_id'] = Discord::getPrivateChannelId($discord_id);
}
}*/
if ($request->hasFile('avatar')) { if ($request->hasFile('avatar')) {
$avatar = $request->file('avatar'); $avatar = $request->file('avatar');
$file_name = $user->ident.'.'.$avatar->getClientOriginalExtension(); $file_name = $user->ident.'.'.$avatar->getClientOriginalExtension();
@@ -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');
@@ -75,44 +70,40 @@ class SimBriefController
return redirect(route('frontend.flights.index')); return redirect(route('frontend.flights.index'));
} }
// Generate SimBrief Static ID
$static_id = $user->ident.'_'.$flight->id;
// 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);
}
return view('flights.simbrief_aircraft', [ return view('flights.simbrief_aircraft', [
'flight' => $flight, 'flight' => $flight,
'aircrafts' => $aircraft, 'aircrafts' => $aircrafts,
'subfleets' => $subfleets,
]); ]);
} }
@@ -129,7 +120,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 +215,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,
@@ -239,7 +230,6 @@ class SimBriefController
'tpayload' => $tpayload, 'tpayload' => $tpayload,
'tcargoload' => $tcargoload, 'tcargoload' => $tcargoload,
'loaddist' => implode(' ', $loaddist), 'loaddist' => implode(' ', $loaddist),
'static_id' => $static_id,
]); ]);
} }
@@ -252,11 +242,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 +255,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'),
]); ]);
} }
@@ -381,31 +360,6 @@ class SimBriefController
]); ]);
} }
/**
* Get the latest generated OFP. Pass in two additional items, the Simbrief userid and static_id
* This will get the latest edited/regenerated of from Simbrief and update our records
* We do not need to send the fares again, so used an empty array
*/
public function update_ofp(Request $request)
{
/** @var User $user */
$user = Auth::user();
$ofp_id = $request->input('ofp_id');
$flight_id = $request->input('flight_id');
$aircraft_id = $request->input('aircraft_id');
$sb_userid = $request->input('sb_userid');
$sb_static_id = $request->input('sb_static_id');
$fares = [];
$simbrief = $this->simBriefSvc->downloadOfp($user->id, $ofp_id, $flight_id, $aircraft_id, $fares, $sb_userid, $sb_static_id);
if ($simbrief === null) {
$error = new AssetNotFound(new Exception('Simbrief OFP not found'));
return $error->getResponse();
}
return redirect(route('frontend.simbrief.briefing', [$ofp_id]));
}
/** /**
* Generate the API code * Generate the API code
* *
@@ -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();
@@ -25,6 +25,7 @@ use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Validator; use Illuminate\Support\Facades\Validator;
use Illuminate\View\View; use Illuminate\View\View;
use function in_array; use function in_array;
use Laracasts\Flash\Flash;
use RuntimeException; use RuntimeException;
class InstallerController extends Controller class InstallerController extends Controller
@@ -3,32 +3,49 @@
namespace App\Http\Controllers\System; namespace App\Http\Controllers\System;
use App\Contracts\Controller; use App\Contracts\Controller;
use App\Repositories\KvpRepository;
use App\Services\AnalyticsService;
use App\Services\Installer\InstallerService; use App\Services\Installer\InstallerService;
use App\Services\Installer\MigrationService; use App\Services\Installer\MigrationService;
use App\Services\Installer\SeederService; use App\Services\Installer\SeederService;
use Codedge\Updater\UpdaterManager;
use function count; use function count;
use Illuminate\Contracts\View\Factory;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use Illuminate\View\View;
class UpdateController extends Controller class UpdateController extends Controller
{ {
private $analyticsSvc;
private $installerSvc; private $installerSvc;
private $kvpRepo;
private $migrationSvc; private $migrationSvc;
private $seederSvc; private $seederSvc;
private $updateManager;
/** /**
* @param AnalyticsService $analyticsSvc
* @param InstallerService $installerSvc * @param InstallerService $installerSvc
* @param KvpRepository $kvpRepo
* @param MigrationService $migrationSvc * @param MigrationService $migrationSvc
* @param SeederService $seederSvc * @param SeederService $seederSvc
* @param UpdaterManager $updateManager
*/ */
public function __construct( public function __construct(
AnalyticsService $analyticsSvc,
InstallerService $installerSvc, InstallerService $installerSvc,
KvpRepository $kvpRepo,
MigrationService $migrationSvc, MigrationService $migrationSvc,
SeederService $seederSvc SeederService $seederSvc,
UpdaterManager $updateManager
) { ) {
$this->analyticsSvc = $analyticsSvc;
$this->migrationSvc = $migrationSvc; $this->migrationSvc = $migrationSvc;
$this->seederSvc = $seederSvc; $this->seederSvc = $seederSvc;
$this->installerSvc = $installerSvc; $this->installerSvc = $installerSvc;
$this->kvpRepo = $kvpRepo;
$this->updateManager = $updateManager;
} }
/** /**
@@ -90,4 +107,38 @@ class UpdateController extends Controller
{ {
return redirect('/admin'); return redirect('/admin');
} }
/**
* Show the update page with the latest version
*
* @return Factory|View
*/
public function updater()
{
$version = $this->kvpRepo->get('latest_version_tag');
return view('system.updater.downloader/downloader', [
'version' => $version,
]);
}
/**
* Download the actual update and then forward the user to the updater page
*
* @return mixed
*/
public function update_download()
{
$version = $this->kvpRepo->get('latest_version_tag');
if (empty($version)) {
return view('system.updater.steps.step1-no-update');
}
$release = $this->updateManager->source('github')->fetch($version);
$this->updateManager->source('github')->update($release);
$this->analyticsSvc->sendUpdate();
Log::info('Update completed to '.$version.', redirecting');
return redirect('/update');
}
} }
-3
View File
@@ -50,9 +50,6 @@ class ApiAuth implements Middleware
return $user; return $user;
}); });
// Force english locale for API
app()->setLocale('en');
return $next($request); return $next($request);
} }
-1
View File
@@ -15,7 +15,6 @@ class JsonResponse implements Middleware
{ {
$response = $next($request); $response = $next($request);
$response->headers->set('Content-Type', 'application/json'); $response->headers->set('Content-Type', 'application/json');
$response->headers->set('charset', 'utf-8');
return $response; return $response;
} }
+1 -1
View File
@@ -19,7 +19,7 @@ class FileRequest extends FormRequest
return [ return [
'distance' => 'required|numeric', 'distance' => 'required|numeric',
'flight_time' => 'required|integer', 'flight_time' => 'required|integer',
'fuel_used' => 'sometimes|numeric', 'fuel_used' => 'required|numeric',
'block_time' => 'sometimes|integer', 'block_time' => 'sometimes|integer',
'airline_id' => 'sometimes|exists:airlines,id', 'airline_id' => 'sometimes|exists:airlines,id',
'aircraft_id' => 'sometimes|exists:aircraft,id', 'aircraft_id' => 'sometimes|exists:aircraft,id',
@@ -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;
}
}
+1 -1
View File
@@ -18,7 +18,7 @@ class News extends Resource
$res = parent::toArray($request); $res = parent::toArray($request);
$res['user'] = [ $res['user'] = [
'id' => $this->user->id, 'id' => $this->user->id,
'name' => $this->user->name_private, 'name' => $this->user->name,
]; ];
return $res; 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;
}
}
-22
View File
@@ -1,22 +0,0 @@
<?php
namespace App\Listeners;
use Illuminate\Log\Events\MessageLogged;
use Symfony\Component\Console\Output\ConsoleOutput;
/**
* Show logs in the console
*
* https://stackoverflow.com/questions/48264479/log-laravel-with-artisan-output
*/
class MessageLoggedListener
{
public function handle(MessageLogged $event)
{
if (app()->runningInConsole() && app()->environment() !== 'testing') {
$output = new ConsoleOutput();
$output->writeln("<$event->level>$event->message</$event->level>");
}
}
}
+4 -1
View File
@@ -6,7 +6,10 @@ use App\Contracts\Listener;
use App\Events\PirepPrefiled; use App\Events\PirepPrefiled;
/** /**
* Handler for PIREP events * Look for and run any of the award classes. Don't modify this.
* See the documentation on creating awards:
*
* @url http://docs.phpvms.net/customizing/awards
*/ */
class PirepEventsHandler extends Listener class PirepEventsHandler extends Listener
{ {
-46
View File
@@ -7,14 +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 name * @property string name
* @property string icao * @property string icao
* @property string registration * @property string registration
@@ -23,7 +20,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 +30,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',
@@ -77,14 +71,6 @@ class Aircraft extends Model
'zfw' => 'nullable|numeric', 'zfw' => 'nullable|numeric',
]; ];
/**
* @return string
*/
public function getIdentAttribute(): string
{
return $this->registration.' ('.$this->icao.')';
}
/** /**
* See if this aircraft is active * See if this aircraft is active
* *
@@ -105,46 +91,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');
+2 -8
View File
@@ -6,7 +6,6 @@ use App\Contracts\Model;
use App\Models\Enums\JournalType; use App\Models\Enums\JournalType;
use App\Models\Traits\FilesTrait; use App\Models\Traits\FilesTrait;
use App\Models\Traits\JournalTrait; use App\Models\Traits\JournalTrait;
use Illuminate\Support\Str;
/** /**
* Class Airline * Class Airline
@@ -85,7 +84,7 @@ class Airline extends Model
*/ */
public function setIataAttribute($iata) public function setIataAttribute($iata)
{ {
$this->attributes['iata'] = Str::upper($iata); $this->attributes['iata'] = strtoupper($iata);
} }
/** /**
@@ -95,7 +94,7 @@ class Airline extends Model
*/ */
public function setIcaoAttribute($icao): void public function setIcaoAttribute($icao): void
{ {
$this->attributes['icao'] = Str::upper($icao); $this->attributes['icao'] = strtoupper($icao);
} }
public function subfleets() public function subfleets()
@@ -103,11 +102,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 -1
View File
@@ -6,7 +6,7 @@ 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
-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',
+1 -1
View File
@@ -77,7 +77,7 @@ class Days extends Enum
*/ */
public static function in($mask, $day): bool public static function in($mask, $day): bool
{ {
return in_mask($mask, $day); return ($mask & $day) === $day;
} }
/** /**
+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 -4
View File
@@ -33,8 +33,7 @@ class PirepStatus extends Enum
public const LANDED = 'LAN'; public const LANDED = 'LAN';
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_DECENT = 'EMG';
public const PAUSED = 'PSD';
protected static $labels = [ protected static $labels = [
self::INITIATED => 'pireps.status.initialized', self::INITIATED => 'pireps.status.initialized',
@@ -59,7 +58,6 @@ class PirepStatus extends Enum
self::LANDED => 'pireps.status.landed', self::LANDED => 'pireps.status.landed',
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_DECENT => 'pireps.status.emerg_decent',
self::PAUSED => 'pireps.status.paused',
]; ];
} }
+1 -2
View File
@@ -13,7 +13,6 @@ use App\Models\Traits\ReferenceTrait;
* @property string flight_type * @property string flight_type
* @property string ref_model * @property string ref_model
* @property string ref_model_id * @property string ref_model_id
* @property bool charge_to_user
* *
* @mixin \Illuminate\Database\Eloquent\Builder * @mixin \Illuminate\Database\Eloquent\Builder
*/ */
@@ -37,7 +36,7 @@ class Expense extends Model
]; ];
public static $rules = [ public static $rules = [
'active' => 'bool', 'active' => 'boolean',
'airline_id' => 'integer', 'airline_id' => 'integer',
'amount' => 'float', 'amount' => 'float',
'multiplier' => 'bool', 'multiplier' => 'bool',
+4 -4
View File
@@ -136,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;
+2 -8
View File
@@ -3,19 +3,13 @@
namespace App\Models; namespace App\Models;
use App\Contracts\Model; use App\Contracts\Model;
use Illuminate\Notifications\Notifiable;
/** /**
* @property int id * @property string subject
* @property int|mixed user_id * @property string body
* @property string subject
* @property string body
* @property User user
*/ */
class News extends Model class News extends Model
{ {
use Notifiable;
public $table = 'news'; public $table = 'news';
protected $fillable = [ protected $fillable = [
+20 -33
View File
@@ -3,8 +3,6 @@
namespace App\Models; namespace App\Models;
use App\Contracts\Model; use App\Contracts\Model;
use App\Events\PirepStateChange;
use App\Events\PirepStatusChange;
use App\Models\Enums\AcarsType; use App\Models\Enums\AcarsType;
use App\Models\Enums\PirepFieldSource; use App\Models\Enums\PirepFieldSource;
use App\Models\Enums\PirepState; use App\Models\Enums\PirepState;
@@ -12,9 +10,7 @@ use App\Models\Traits\HashIdTrait;
use App\Support\Units\Distance; use App\Support\Units\Distance;
use App\Support\Units\Fuel; use App\Support\Units\Fuel;
use Carbon\Carbon; use Carbon\Carbon;
use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Kleemans\AttributeEvents;
/** /**
* @property string id * @property string id
@@ -48,9 +44,8 @@ use Kleemans\AttributeEvents;
* @property Flight|null flight * @property Flight|null flight
* @property Collection fields * @property Collection fields
* @property string status * @property string status
* @property int state * @property bool state
* @property int source * @property string source
* @property string source_name
* @property Carbon submitted_at * @property Carbon submitted_at
* @property Carbon created_at * @property Carbon created_at
* @property Carbon updated_at * @property Carbon updated_at
@@ -61,9 +56,7 @@ use Kleemans\AttributeEvents;
*/ */
class Pirep extends Model class Pirep extends Model
{ {
use AttributeEvents;
use HashIdTrait; use HashIdTrait;
use Notifiable;
public $table = 'pireps'; public $table = 'pireps';
@@ -143,14 +136,6 @@ class Pirep extends Model
'route' => 'nullable', 'route' => 'nullable',
]; ];
/**
* Auto-dispatch events for lifecycle state changes
*/
protected $dispatchesEvents = [
'status:*' => PirepStatusChange::class,
'state:*' => PirepStateChange::class,
];
/* /*
* If a PIREP is in these states, then it can't be changed. * If a PIREP is in these states, then it can't be changed.
*/ */
@@ -195,39 +180,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;
-1
View File
@@ -11,7 +11,6 @@ use App\Models\Enums\PirepFieldSource;
* @property string slug * @property string slug
* @property string value * @property string value
* @property string source * @property string source
* @property Pirep pirep
* *
* @method static updateOrCreate(array $array, array $array1) * @method static updateOrCreate(array $array, array $array1)
*/ */
+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()
-6
View File
@@ -20,7 +20,6 @@ use App\Models\Traits\FilesTrait;
* @property float cost_delay_minute * @property float cost_delay_minute
* @property Airline airline * @property Airline airline
* @property Airport hub * @property Airport hub
* @property int fuel_type
*/ */
class Subfleet extends Model class Subfleet extends Model
{ {
@@ -107,9 +106,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');
}
}
+6 -24
View File
@@ -3,11 +3,11 @@
namespace App\Models; namespace App\Models;
use App\Models\Enums\JournalType; use App\Models\Enums\JournalType;
use App\Models\Enums\PirepState;
use App\Models\Traits\JournalTrait; 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
@@ -33,17 +33,13 @@ use Staudenmeir\EloquentHasManyDeep\HasRelationships;
* @property Rank rank * @property Rank rank
* @property Journal journal * @property Journal journal
* @property int rank_id * @property int rank_id
* @property string discord_id
* @property int state * @property int state
* @property string last_ip
* @property bool opt_in * @property bool opt_in
* @property Pirep[] pireps
* @property string last_pirep_id * @property string last_pirep_id
* @property Pirep last_pirep * @property Pirep last_pirep
* @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 +50,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';
@@ -71,8 +66,6 @@ class User extends Authenticatable
'pilot_id', 'pilot_id',
'airline_id', 'airline_id',
'rank_id', 'rank_id',
'discord_id',
'discord_private_channel_id',
'api_key', 'api_key',
'country', 'country',
'home_airport_id', 'home_airport_id',
@@ -87,7 +80,6 @@ class User extends Authenticatable
'status', 'status',
'toc_accepted', 'toc_accepted',
'opt_in', 'opt_in',
'last_ip',
'created_at', 'created_at',
'updated_at', 'updated_at',
]; ];
@@ -97,9 +89,7 @@ class User extends Authenticatable
*/ */
protected $hidden = [ protected $hidden = [
'api_key', 'api_key',
'discord_id',
'password', 'password',
'last_ip',
'remember_token', 'remember_token',
]; ];
@@ -129,7 +119,7 @@ class User extends Authenticatable
{ {
$length = setting('pilots.id_length'); $length = setting('pilots.id_length');
return optional($this->airline)->icao.str_pad($this->pilot_id, $length, '0', STR_PAD_LEFT); return $this->airline->icao.str_pad($this->pilot_id, $length, '0', STR_PAD_LEFT);
} }
/** /**
@@ -194,7 +184,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;
@@ -260,21 +251,12 @@ class User extends Authenticatable
public function pireps() public function pireps()
{ {
return $this->hasMany(Pirep::class, 'user_id'); return $this->hasMany(Pirep::class, 'user_id')
->where('state', '!=', PirepState::CANCELLED);
} }
public function rank() public function rank()
{ {
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
*/ */
@@ -1,145 +0,0 @@
<?php
namespace App\Notifications\Channels\Discord;
use Carbon\Carbon;
/**
* Original is from https://gist.github.com/freekmurze/e4415090f650e070d3de8b905875cf78
*
* Markdown guide: https://birdie0.github.io/discord-webhooks-guide/other/discord_markdown.html
*/
class DiscordMessage
{
const COLOR_SUCCESS = '#0B6623';
const COLOR_WARNING = '#FD6A02';
const COLOR_ERROR = '#ED2939';
public $webhook_url;
protected $title;
protected $url;
protected $description;
protected $timestamp;
protected $footer;
protected $color;
protected $author = [];
protected $fields = [];
/**
* Supply the webhook URL that this should be going to
*/
public function webhook(string $url): self
{
$this->webhook_url = $url;
return $this;
}
/**
* Title of the notification
*/
public function title(string $title): self
{
$this->title = $title;
return $this;
}
public function url(string $url): self
{
$this->url = $url;
return $this;
}
/**
* @param array|string $descriptionLines
*/
public function description($descriptionLines): self
{
if (!is_array($descriptionLines)) {
$descriptionLines = [$descriptionLines];
}
$this->description = implode(PHP_EOL, $descriptionLines);
return $this;
}
/**
* Set the author information:
* [
* 'name' => '',
* 'url' => '',
* 'icon_url' => '',
*/
public function author(array $author): self
{
$this->author = $author;
return $this;
}
/**
* Set the fields
*/
public function fields(array $fields): self
{
$this->fields = [];
foreach ($fields as $name => $value) {
$this->fields[] = [
'name' => '**'.$name.'**', // bold
'value' => $value,
'inline' => true,
];
}
return $this;
}
public function footer(string $footer): self
{
$this->footer = $footer;
return $this;
}
public function success(): self
{
$this->color = static::COLOR_SUCCESS;
return $this;
}
public function warning(): self
{
$this->color = static::COLOR_WARNING;
return $this;
}
public function error(): self
{
$this->color = static::COLOR_ERROR;
return $this;
}
public function toArray(): array
{
$embeds = [
'title' => $this->title,
'url' => $this->url,
'type' => 'rich',
'description' => $this->description,
'author' => $this->author,
'timestamp' => Carbon::now('UTC'),
];
if (!empty($this->fields)) {
$embeds['fields'] = $this->fields;
}
if (!empty($this->footer)) {
$embeds['footer'] = [
'text' => $this->footer,
];
}
return [
'embeds' => [$embeds],
];
}
}
@@ -1,38 +0,0 @@
<?php
namespace App\Notifications\Channels\Discord;
use App\Contracts\Notification;
use App\Support\HttpClient;
use GuzzleHttp\Exception\RequestException;
use GuzzleHttp\Psr7;
use Illuminate\Support\Facades\Log;
class DiscordWebhook
{
private $httpClient;
public function __construct(HttpClient $httpClient)
{
$this->httpClient = $httpClient;
}
public function send($notifiable, Notification $notification)
{
$message = $notification->toDiscordChannel($notifiable);
if ($message === null || empty($message->webhook_url)) {
Log::debug('Discord notifications not configured, skipping');
return;
}
try {
$data = $message->toArray();
$this->httpClient->post($message->webhook_url, $data);
} catch (RequestException $e) {
$request = Psr7\Message::toString($e->getRequest());
$response = Psr7\Message::toString($e->getResponse());
Log::error('Error sending Discord notification: request: '.$e->getMessage().', '.$request);
Log::error('Error sending Discord notification: response: '.$response);
}
}
}
+1 -1
View File
@@ -17,7 +17,7 @@ trait MailChannel
* @param string $template Markdown template to use * @param string $template Markdown template to use
* @param array $args Arguments to pass to the template * @param array $args Arguments to pass to the template
*/ */
public function setMailable(string $subject, string $template, array $args) public function setMailable($subject, $template, $args)
{ {
$this->mailSubject = $subject; $this->mailSubject = $subject;
$this->mailTemplate = $template; $this->mailTemplate = $template;
@@ -6,13 +6,13 @@ use App\Contracts\Listener;
use App\Events\NewsAdded; use App\Events\NewsAdded;
use App\Events\PirepAccepted; use App\Events\PirepAccepted;
use App\Events\PirepFiled; use App\Events\PirepFiled;
use App\Events\PirepPrefiled;
use App\Events\PirepRejected; use App\Events\PirepRejected;
use App\Events\PirepStatusChange;
use App\Events\UserRegistered; use App\Events\UserRegistered;
use App\Events\UserStateChanged; use App\Events\UserStateChanged;
use App\Models\Enums\UserState; use App\Models\Enums\UserState;
use App\Models\User; use App\Models\User;
use App\Notifications\Messages\PirepSubmitted;
use App\Notifications\Messages\UserPending;
use App\Notifications\Messages\UserRejected; use App\Notifications\Messages\UserRejected;
use App\Notifications\Notifiables\Broadcast; use App\Notifications\Notifiables\Broadcast;
use Exception; use Exception;
@@ -23,19 +23,17 @@ use Illuminate\Support\Facades\Notification;
/** /**
* Listen for different events and map them to different notifications * Listen for different events and map them to different notifications
*/ */
class NotificationEventsHandler extends Listener class EventHandler extends Listener
{ {
private static $broadcastNotifyable; private static $broadcastNotifyable;
public static $callbacks = [ public static $callbacks = [
NewsAdded::class => 'onNewsAdded', NewsAdded::class => 'onNewsAdded',
PirepPrefiled::class => 'onPirepPrefile', PirepAccepted::class => 'onPirepAccepted',
PirepStatusChange::class => 'onPirepStatusChange', PirepFiled::class => 'onPirepFile',
PirepAccepted::class => 'onPirepAccepted', PirepRejected::class => 'onPirepRejected',
PirepFiled::class => 'onPirepFile', UserRegistered::class => 'onUserRegister',
PirepRejected::class => 'onPirepRejected', UserStateChanged::class => 'onUserStateChange',
UserRegistered::class => 'onUserRegister',
UserStateChanged::class => 'onUserStateChange',
]; ];
public function __construct() public function __construct()
@@ -58,7 +56,6 @@ class NotificationEventsHandler extends Listener
} }
try { try {
// $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());
@@ -120,24 +117,19 @@ class NotificationEventsHandler extends Listener
.$event->user->ident.' is ' .$event->user->ident.' is '
.UserState::label($event->user->state).', sending active email'); .UserState::label($event->user->state).', sending active email');
/*
* Send all of the admins a notification that a new user registered
*/
$this->notifyAdmins(new Messages\AdminUserRegistered($event->user));
/* /*
* Send the user a confirmation email * Send the user a confirmation email
*/ */
if ($event->user->state === UserState::ACTIVE) { if ($event->user->state === UserState::ACTIVE) {
$this->notifyUser($event->user, new Messages\UserRegistered($event->user)); $this->notifyUser($event->user, new Messages\UserRegistered($event->user));
} elseif ($event->user->state === UserState::PENDING) { } elseif ($event->user->state === UserState::PENDING) {
$this->notifyUser($event->user, new Messages\UserPending($event->user)); $this->notifyUser($event->user, new UserPending($event->user));
} }
/*
* Send all of the admins a notification that a new user registered
*/
$this->notifyAdmins(new Messages\AdminUserRegistered($event->user));
/**
* Discord and other notifications
*/
Notification::send([$event->user], new Messages\AdminUserRegistered($event->user));
} }
/** /**
@@ -160,34 +152,15 @@ class NotificationEventsHandler extends Listener
} }
} }
/**
* Prefile notification
*/
public function onPirepPrefile(PirepPrefiled $event): void
{
Log::info('NotificationEvents::onPirepPrefile: '.$event->pirep->id.' prefiled');
Notification::send([$event->pirep], new Messages\PirepPrefiled($event->pirep));
}
/**
* Status Change notification
*/
public function onPirepStatusChange(PirepStatusChange $event): void
{
Log::info('NotificationEvents::onPirepStatusChange: '.$event->pirep->id.' prefiled');
Notification::send([$event->pirep], new Messages\PirepStatusChanged($event->pirep));
}
/** /**
* Notify the admins that a new PIREP has been filed * Notify the admins that a new PIREP has been filed
* *
* @param PirepFiled $event * @param \App\Events\PirepFiled $event
*/ */
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 ');
$this->notifyAdmins(new Messages\PirepSubmitted($event->pirep)); $this->notifyAdmins(new PirepSubmitted($event->pirep));
Notification::send([$event->pirep], new Messages\PirepSubmitted($event->pirep));
} }
/** /**
@@ -221,6 +194,5 @@ class NotificationEventsHandler extends Listener
{ {
Log::info('NotificationEvents::onNewsAdded'); Log::info('NotificationEvents::onNewsAdded');
$this->notifyAllUsers(new Messages\NewsAdded($event->news)); $this->notifyAllUsers(new Messages\NewsAdded($event->news));
Notification::send([$event->news], new Messages\NewsAdded($event->news));
} }
} }
@@ -4,15 +4,14 @@ 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;
class AdminUserRegistered extends Notification implements ShouldQueue class AdminUserRegistered extends Notification
{ {
use MailChannel; use MailChannel;
public $channels = ['mail'];
private $user; private $user;
/** /**
@@ -32,32 +31,6 @@ class AdminUserRegistered extends Notification implements ShouldQueue
); );
} }
public function via($notifiable)
{
return ['mail', DiscordWebhook::class];
}
/**
* Send a Discord notification
*
* @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 [

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