Compare commits

...
Author SHA1 Message Date
snyk-bot a5830dcc08 fix: package.json & package-lock.json to reduce vulnerabilities
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-JS-Y18N-1021887
2020-11-18 02:24:37 +00:00
Nabeel Shahzad a2de532f72 Merge branch 'dev' of https://github.com/nabeelio/phpvms into dev 2020-11-02 11:57:27 -05:00
Nabeel Shahzad a52d844719 Set flight_id to be fillable 2020-11-02 11:57:25 -05:00
Timothy Sturm fd814bc79e * Fixed broken links on README
* Fixed broken links on README

* Misc. edits to markdown formatting, Title Grammer, and Stylizing the phpVMS brand.
2020-10-31 18:43:00 -04:00
Nabeel Shahzad 0fa00206ce Make sure stdclass is returned in flight fields 2020-10-29 12:38:40 -04:00
Nabeel Shahzad a58237b04b Allow flight_id to be nullable 2020-10-27 21:47:19 -04:00
Nabeel S dc7efc981c Refactor fares inheritance #905 (#906) 2020-10-27 18:46:15 -04:00
Yash Govekar 060bebf8fe Accept Pirep button not changing row inline #598 (#880) 2020-10-26 10:18:00 -04:00
Nabeel Shahzad aaaf2e7c00 Make sure capacity is an integer 2020-10-24 16:04:09 -04:00
Nabeel S 1be68d1e63 Flight/Subfleet fares not returning in API #899 (#900)
Make sure proper fares are returned from the API #899
2020-10-24 15:11:08 -04:00
Nabeel Shahzad b83f7dcac8 Updated seed data for dev 2020-10-24 09:26:14 -04:00
Nabeel S c5de2fd8b1 Fix for base map/providers #895 (#897) 2020-10-23 08:08:41 -04:00
Nabeel S b85d0e6a3e Expose Leaflet base options to templates #895 (#896) 2020-10-23 07:35:44 -04:00
Nabeel S b37bd2cd7b Change award events handler to subscription #888 (#894) 2020-10-23 07:28:22 -04:00
Nabeel S 584d37f230 FlightRouteAwards - fix if last pirep is empty/other error conditions (#886) 2020-10-22 16:25:52 -04:00
Nabeel Shahzad 1c9d1c1733 Extra logs/skip module seed pending 2020-10-21 14:12:38 -04:00
Nabeel S cd18442207 Fixes for installer/modules race condition (#883) 2020-10-21 13:28:54 -04:00
Yash Govekar 716ba38b6d Default values for automatically added airports #829 (#878) 2020-10-20 15:25:13 -04:00
Yash Govekar c0514b381b Fixed exporting expenses (#877) 2020-10-19 15:22:06 -04:00
Yash Govekar 5803487d51 Installing and managing modules from admin panel (#847) 2020-10-19 10:10:28 -04:00
Snyk bot ca220f1cdf fix: package.json & package-lock.json to reduce vulnerabilities (#873)
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-JS-AJV-584908
- https://snyk.io/vuln/SNYK-JS-JQUERY-565129
- https://snyk.io/vuln/SNYK-JS-JQUERY-567880
- https://snyk.io/vuln/SNYK-JS-SELECT2-456562
- https://snyk.io/vuln/SNYK-JS-SOCKJS-575261
- https://snyk.io/vuln/SNYK-JS-WEBPACKDEVSERVER-72405
- https://snyk.io/vuln/SNYK-JS-YARGSPARSER-560381
- https://snyk.io/vuln/npm:mem:20180117
2020-10-16 11:01:24 -04:00
Nabeel Shahzad 75a0a4c87a Update FareService.php 2020-10-13 18:12:52 -04:00
Nabeel Shahzad 3b6800077f Preload fares with PIREP 2020-10-13 18:12:14 -04:00
Nabeel Shahzad bf878a98a4 Extra logging around fares 2020-10-13 18:10:31 -04:00
DaGeek d001704880 Adding a new AwardClass for Flight Time (#869)
Adding a new AwardClass for Flight Time
2020-10-13 17:07:12 -04:00
DaGeek 5371989921 Cosmetic Fix to display Award Images in Admin View (#870)
Fix to correctly display the Award image in the admin UI
2020-10-13 15:41:16 -04:00
DaGeek 6c553569bf Create FlightRouteAwards.php (#865)
Award - FlightRoute- this allows the Admins to create an Award that will be granted if a Pilot completes a flight with a defined Departure and Arrival Airport
2020-10-12 18:54:42 -04:00
Nabeel Shahzad 9eb7dd6913 Update doc links 2020-10-12 15:15:05 -04:00
Nabeel S dc007f6d9e Bids are missing subfleets in API response #867 (#868)
Bids are missing subfleets in API response #867
2020-10-12 12:49:11 -04:00
Nabeel S 193fbd369d Show awards on user profile #703 (#866) 2020-10-11 16:06:09 -04:00
Botric 151f188886 Update pirep_card.blade.php (#857)
Update pirep_card.blade.php
2020-10-10 15:24:28 -04:00
Nabeel S 69d89511be Inherited value can't be removed #811 (#863)
Inherited value can't be removed #811
2020-10-10 15:24:10 -04:00
Nabeel S 48087fb05f Metar: TEMPO and trend causing issue with values being overwritten (#862)
Metar: TEMPO and trend causing issue with values being overwritten
2020-10-10 14:55:12 -04:00
Nabeel S c702b01a87 Add tests that rank shouldn't auto change (#840) 2020-10-10 14:50:00 -04:00
DaGeek 0a5194b92e Small Cosmetic Change to Rank & Home Airport Display (#852)
Cosmetic Change to Rank & Home Airport Display
2020-10-09 17:45:16 -04:00
Nabeel Shahzad 24aca506fc Update UserController.php 2020-10-06 19:26:52 -04:00
Nabeel Shahzad 365e33f5f8 Redirect show() to edit() 2020-10-06 19:10:42 -04:00
Nabeel Shahzad 7a75e0f5ad Fix missing $countries 2020-10-06 18:52:34 -04:00
Botric 93da2ca061 Cosmetic change to standardise boxes on profile (#853) 2020-10-04 12:48:12 -04:00
vgpastor 5363e4aa0f Add API Key visual protection (#851)
Add API Key visual protection
2020-10-03 11:13:28 -04:00
Nabeel S 95a40d3565 Make sure proper subfleets are returned as part of the user profile #848 (#849)
* Make sure proper subfleets are returned as part of the user profile #848

* Formatting
2020-09-30 12:58:45 -04:00
Nabeel S 98aa362935 Fix subfleets not returning proper fare counts #831 (#846)
Fix subfleets not returning proper fare counts #831
2020-09-29 13:21:24 -04:00
Yash Govekar b6603bd178 Updated Route Service Provider that was mismatching API and ADMIN Section (#845) 2020-09-29 13:09:00 -04:00
Yash Govekar 2c539d349d Fix controller namespace in module generation #714
Updated Module Files
2020-09-28 16:04:51 -04:00
Nabeel Shahzad 5df28eb027 Fix module main service provider name 2020-09-27 12:13:24 -04:00
yashris 0dbf8b8652 Public JS files Updated! (#839) 2020-09-27 09:03:46 -04:00
yashris 5856f88a0c Updated index.js inside Map folder (#837) 2020-09-24 09:56:52 -04:00
Nabeel Shahzad 5f9b9399e9 Use $current_airport 2020-09-23 14:39:10 -04:00
Nabeel S 77fe6679ce Update module generation #714 (#716)
* Update module generation #714

* Fix method signatures

* Fix paths within stubs, use single provider.stub file

* Add separate index controller

* Update module generation #714

* Fix method signatures

* Fix paths within stubs, use single provider.stub file

* Update module generation

Disable/lower the cache time as found as a workaround in https://github.com/nWidart/laravel-modules/issues/995

* Update editorconfig for line endings

* Formatting

* Formatting
2020-09-20 19:10:52 -04:00
Nabeel Shahzad 435fa32663 Fix aircraft field name #824 2020-09-15 15:41:53 -04:00
Nabeel Shahzad 78ca06e9dc Add optional() around aircraft info #824 2020-09-14 16:17:03 -04:00
Nabeel Shahzad 2dd3dd5814 Make sure we're getting only active expenses 2020-09-12 15:17:10 -04:00
Nabeel Shahzad ac7a5a65e5 Update cron path 2020-09-11 16:57:50 -04:00
Nabeel Shahzad c5ab0978db Force visible flag to true for imports #818 2020-09-11 09:18:27 -04:00
dependabot[bot] 8398d94c0a Bump js-yaml from 3.11.0 to 3.13.1 (#810)
Bumps [js-yaml](https://github.com/nodeca/js-yaml) from 3.11.0 to 3.13.1.
- [Release notes](https://github.com/nodeca/js-yaml/releases)
- [Changelog](https://github.com/nodeca/js-yaml/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nodeca/js-yaml/compare/3.11.0...3.13.1)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-09-10 17:06:01 -04:00
Nabeel S 1db3295213 Disable autocomplete in admin forms #816 (#817) 2020-09-10 16:42:11 -04:00
Nabeel Shahzad 5dcbd01c00 Update links to some docs 2020-09-04 14:08:14 -04:00
Nabeel Shahzad c6d12802a4 Fix link to assets docs 2020-09-04 13:32:39 -04:00
Nabeel Shahzad 07de33605b Switch toolchain from yarn to npm 2020-09-04 13:28:17 -04:00
Nabeel Shahzad ec9ef9c1c2 Add notes to refer to docs when modifying the JS files 2020-09-04 11:50:05 -04:00
Nabeel Shahzad 23962a1abb Add fileinfo ext to requirements #735
closes #735
2020-09-04 11:28:33 -04:00
Nabeel Shahzad 9a735d2935 Update language for subfleet fare 2020-09-04 10:09:53 -04:00
Nabeel Shahzad 51004b143c Fix validator type for aircraft #805 2020-09-03 15:14:26 -04:00
Nabeel S 50a0b89caa Add MTOW and ZFW to aircraft editor #775 (#805)
Add MTOW and ZFW to aircraft editor #775
2020-09-03 13:29:24 -04:00
Nabeel S e99c22b007 Notifications fixes (#804)
* Emails not sending #795 #722

* Fix for news items not being sent; refactor some events; check for opt-in #722

* Formatting

* Remove extra parameter
2020-09-03 12:50:42 -04:00
Nabeel Shahzad 55fa01478d Fix path for bootstrap file #798 2020-09-02 18:52:52 -04:00
Nabeel Shahzad 552196ce57 Fix root detection #798 2020-09-02 18:47:38 -04:00
Nabeel S 7aa089bd88 Update Laravel/composer dependencies (#803) 2020-09-02 18:15:05 -04:00
Nabeel S 1e4b0d629a Detect the phpvms folder one root level above #798 (#799) 2020-09-01 10:38:45 -04:00
Timothy Sturm febfff5f12 Update MailChannel.php (#793)
Update from email #792
2020-08-21 15:54:26 -04:00
Nabeel S cdf7b13b5b Allow any airport to be flown from #783 (#788)
Allow any airport to be flown from #783
2020-08-17 17:06:02 -04:00
Nabeel S 51186bed7c Fix for aircraft not being detected at departure airport #781 (#789)
Aircraft not being checked/detected at departure airport #781
2020-08-17 16:44:31 -04:00
Nabeel Shahzad ac1dc49377 Replace IP in test 2020-08-15 13:54:01 -04:00
Nabeel Shahzad be72571185 Check if the root domain is an IP address 2020-08-15 13:50:58 -04:00
Nabeel Shahzad d3e6d2c49a Add extra logging for user not being at proper airport 2020-08-14 10:26:21 -04:00
Nabeel S 4fa58cec5a Fix clear cache errors with duplicate route names #759 (#787) 2020-08-13 17:53:30 -04:00
Nabeel S 27316f96e8 Fix missing user fields #785 (#786) 2020-08-13 17:44:41 -04:00
Nabeel Shahzad e5ed66b372 Fix attribute type for PIREP status 2020-08-12 22:02:20 -04:00
Nabeel Shahzad ee6982f558 Build fix/StyleCI 2020-08-12 14:46:08 -04:00
Nabeel Shahzad 4f46e75515 Check for active flag for user fields in registration 2020-08-12 14:39:00 -04:00
dependabot[bot]andNabeel S 3ac03d9716 Bump elliptic from 6.5.2 to 6.5.3 (#780)
Bumps [elliptic](https://github.com/indutny/elliptic) from 6.5.2 to 6.5.3.
- [Release notes](https://github.com/indutny/elliptic/releases)
- [Commits](https://github.com/indutny/elliptic/compare/v6.5.2...v6.5.3)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Nabeel S <nabeelio@users.noreply.github.com>
2020-08-12 09:26:22 -04:00
Nabeel Shahzad ace7c42557 Fix typo for unique email check 2020-08-12 09:06:18 -04:00
Nabeel S 3ebf4f2924 Custom user fields #711 (#772)
Custom user fields during registration and profile edit #711
2020-08-11 17:48:51 -04:00
dependabot[bot] 3739cc8e91 Bump lodash from 4.17.15 to 4.17.19 (#770)
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.15 to 4.17.19.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.15...4.17.19)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-08-11 17:48:16 -04:00
Nabeel S bbb5f1d13c Check for null values when checking pilot ID #760 (#768) 2020-07-14 22:02:35 -04:00
Nabeel S 64e4c91e7e Check public pages for authorization #761 2020-07-10 13:11:38 -04:00
Nabeel S 3e2b1fe42b Add spacing to fare labels #763 (#766) 2020-07-10 09:51:33 -04:00
Nabeel S 420bd7e4ae Add ability to use a link instead of a page #750 (#757)
Add ability to use a link instead of a page #750
2020-06-11 08:27:38 -04:00
Nabeel S e4b1c238f3 Add ACARS update event #755 (#756) 2020-06-09 09:10:40 -04:00
Nabeel S 57e91027c8 Fix the search route for pending PIREPs #752 (#754) 2020-06-08 09:55:57 -04:00
dependabot[bot] 475ad3a66d Bump websocket-extensions from 0.1.3 to 0.1.4 (#753)
Bumps [websocket-extensions](https://github.com/faye/websocket-extensions-node) from 0.1.3 to 0.1.4.
- [Release notes](https://github.com/faye/websocket-extensions-node/releases)
- [Changelog](https://github.com/faye/websocket-extensions-node/blob/master/CHANGELOG.md)
- [Commits](https://github.com/faye/websocket-extensions-node/compare/0.1.3...0.1.4)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2020-06-08 08:56:31 -04:00
Nabeel S 340f52112d Fix public pages not showing properly #708 (#749) 2020-06-05 12:49:22 -04:00
Nabeel Shahzad c6482bd160 Add last_pirep test 2020-06-05 09:19:18 -04:00
Nabeel Shahzad df15053b75 Remove trailing comma 2020-06-04 14:05:51 -04:00
Nabeel S 04b8be1649 Add show_datetime_format(); optional default timezone parameter #741 (#746) 2020-06-04 11:34:30 -04:00
Nabeel S 3d211535f7 Remove Google Analytics #728 (#745)
* Remove Google Analytics #728

* Remove config file

* Don't set the vacentral url
2020-06-04 10:36:55 -04:00
Nabeel S c1408cb8fe Fleet properties not saving #731 (#744) 2020-06-04 08:39:20 -04:00
Nabeel S 519ae600d5 Fix METAR invalid parameter #738 (#743) 2020-06-04 06:30:35 -04:00
Nabeel S 82bae9cc74 Update the flash messages #739 (#742) 2020-06-04 06:11:57 -04:00
Nabeel S 3a07e34259 Add pt-br language #736 (#737)
Add pt-br language #736
2020-06-02 09:10:26 -04:00
Nabeel S 89ca0b49a2 Merge pull request #730 from nabeelio/729-Multi-Expenses
All airports' expenses being applied to PIREP #729
2020-05-26 19:39:29 -04:00
Nabeel Shahzad 5b16c88bcb Fix for all airport expenses being applied #729 2020-05-26 19:13:15 -04:00
Nabeel S c67e45e98e Merge pull request #727 from nabeelio/724-Db-Memory-Syntax-Error
Fix params for launching process #724
2020-05-23 13:02:34 -04:00
Nabeel Shahzad 688be6f75a Fix params for launching process #724 2020-05-23 12:53:39 -04:00
Nabeel S 8527b39fe2 Merge pull request #725 from nabeelio/718-Airline-Active
Check for airline being active; fix tests for L7 #718
2020-05-23 11:55:26 -04:00
Nabeel Shahzad a443908bed Frontend flight controller for active airlines 2020-05-23 11:48:48 -04:00
Nabeel Shahzad c46fc9171c Check for airline being active; fix tests for L7 #718 2020-05-23 11:45:07 -04:00
Nabeel S 71c09aaeb1 Merge pull request #721 from nabeelio/715-Error-Page-Skins
Use theme in error handlers #715
2020-05-23 09:18:07 -04:00
Nabeel Shahzad 5046d26032 Explicitly set theme in error handler, refactor middleware #715 2020-05-23 09:05:38 -04:00
Nabeel S 4cd7eef937 Merge pull request #720 from nabeelio/719-Login-On-Leave
Allow on-leave user to login
2020-05-23 07:47:10 -04:00
Nabeel Shahzad f17cd15b01 Allow on-leave user to login; show alert message and ensure status is updated #719 2020-05-23 07:20:55 -04:00
Nabeel S 5f8053226e Merge pull request #717 from nabeelio/715-Theme
Apply theme globally; add mail templates into theme folder #715
2020-05-22 21:49:22 -04:00
Nabeel Shahzad 09cd7adb6b Apply theme globally; add mail templates into theme folder #715 2020-05-22 19:00:54 -04:00
Nabeel S fb7d988032 Merge pull request #712 from nabeelio/707-Module-Enable
Make sure the Updater module is enabled #707
2020-05-21 22:44:59 -04:00
Nabeel Shahzad eb90d08761 Make sure the Updater module is enabled #707 2020-05-21 22:12:09 -04:00
Nabeel S 1ebb181c36 Merge pull request #710 from nabeelio/707-Update-Error
Auto-Update fixes #707
2020-05-21 12:28:52 -04:00
Nabeel Shahzad 975ee9b88e Fix for update showing available when one isn't #707 2020-05-21 11:50:13 -04:00
Nabeel S 52379c3789 Merge pull request #705 from nabeelio/704-Acars-Map-Center
Fix error with map centering on invalid layers #704
2020-05-19 18:47:27 -04:00
Nabeel Shahzad bcf7acf957 Fix error with map centering on invalid layers #704 2020-05-19 18:07:38 -04:00
Nabeel S 3b1936e110 Merge pull request #699 from nabeelio/698-Login-Pilot-Id
Enable logins using pilot ID #698
2020-05-16 11:59:03 -04:00
Nabeel Shahzad b9aeda1cba Enable logins using pilot ID #698 2020-05-16 11:52:05 -04:00
Nabeel S 00505a1607 Merge pull request #697 from nabeelio/673-Laravel-7
Laravel 7 support #673
2020-05-16 09:37:36 -04:00
Nabeel Shahzad 6ebbe0209e Formatting 2020-05-15 18:38:43 -04:00
Nabeel Shahzad 5754103a17 Bump minimum PHP version to 7.3 2020-05-15 18:22:24 -04:00
Nabeel Shahzad 6078163d75 Initial pass at Laravel 7 support #673 2020-05-15 18:20:23 -04:00
Nabeel S 885e1d599e Merge pull request #696 from nabeelio/693-Public-Folder-Permissions
Installer: Use absolute paths for permissions check #693
2020-05-15 15:56:07 -04:00
Nabeel Shahzad 876457af71 Use absolute paths for permissions check #693 2020-05-15 15:45:54 -04:00
Nabeel S 8c75bd098e Merge pull request #695 from sebiecker/dev
Update Permissions Seed
2020-05-15 12:21:30 -04:00
Sebastian Ecker 585c9578e8 Update Permissions Seed
Aircraft is missing in Permissions Seed
2020-05-15 17:51:41 +02:00
3009 changed files with 74076 additions and 14502 deletions
+5 -1
View File
@@ -1,6 +1,10 @@
# #
root = true root = true
[*]
end_of_line = lf
insert_final_newline = true
[*.js] [*.js]
indent_style = space indent_style = space
indent_size = 2 indent_size = 2
@@ -23,4 +27,4 @@ indent_style = tab
# Matches the exact files either package.json or .travis.yml # Matches the exact files either package.json or .travis.yml
[{package.json, .travis.yml}] [{package.json, .travis.yml}]
indent_style = space indent_style = space
indent_size = 2 indent_size = 2
-1
View File
@@ -6,7 +6,6 @@ language: php
php: php:
- '7.4' - '7.4'
- '7.3' - '7.3'
- '7.2'
#env: #env:
# - DB=mysql # - DB=mysql
+2 -2
View File
@@ -21,9 +21,9 @@
<directory suffix=".php">./app</directory> <directory suffix=".php">./app</directory>
</whitelist> </whitelist>
</filter> </filter>
<listeners> <!--<listeners>
<listener class="NunoMaduro\Collision\Adapters\Phpunit\Listener"/> <listener class="NunoMaduro\Collision\Adapters\Phpunit\Listener"/>
</listeners> </listeners>-->
<php> <php>
<ini name="error_reporting" value="E_ALL"/> <ini name="error_reporting" value="E_ALL"/>
<ini name="display_errors" value="On"/> <ini name="display_errors" value="On"/>
+4 -4
View File
@@ -43,7 +43,7 @@ build:
# This is to build all the stylesheets, etc # This is to build all the stylesheets, etc
.PHONY: build-assets .PHONY: build-assets
build-assets: build-assets:
yarn run production npm run production
.PHONY: install .PHONY: install
install: build install: build
@@ -74,9 +74,9 @@ reload-db:
tests: test tests: test
.PHONY: test .PHONY: test
test: phpcs test:
#php artisan database:create --reset @#php artisan database:create --reset
vendor/bin/phpunit --debug --verbose @vendor/bin/phpunit --verbose
.PHONY: phpcs .PHONY: phpcs
phpcs: phpcs:
+10 -13
View File
@@ -1,20 +1,17 @@
# phpvms <sup>7</sup> # phpVMS <sup>7</sup>
[![Build Status](https://travis-ci.org/nabeelio/phpvms.svg)](https://travis-ci.org/nabeelio/phpvms) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/d668bebb0a3c46bda381af16ce3d9450)](https://www.codacy.com/app/nabeelio/phpvms?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=nabeelio/phpvms&amp;utm_campaign=Badge_Grade) [![Latest Stable Version](https://poser.pugx.org/nabeel/phpvms/v/stable)](https://packagist.org/packages/nabeel/phpvms) ![StyleCI](https://github.styleci.io/repos/93688482/shield?branch=dev) [![License](https://poser.pugx.org/nabeel/phpvms/license)](https://packagist.org/packages/nabeel/phpvms) [![Build Status](https://travis-ci.org/nabeelio/phpvms.svg)](https://travis-ci.org/nabeelio/phpvms) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/d668bebb0a3c46bda381af16ce3d9450)](https://www.codacy.com/app/nabeelio/phpvms?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=nabeelio/phpvms&amp;utm_campaign=Badge_Grade) [![Latest Stable Version](https://poser.pugx.org/nabeel/phpvms/v/stable)](https://packagist.org/packages/nabeel/phpvms) ![StyleCI](https://github.styleci.io/repos/93688482/shield?branch=dev) [![License](https://poser.pugx.org/nabeel/phpvms/license)](https://packagist.org/packages/nabeel/phpvms)
The next phpvms version built on the laravel framework. work in progress. The latest documentation, with installation instructions is available The next phpvms version built on the laravel framework. work in progress. The latest documentation, with installation instructions is available [on the phpVMS documentation](https://docs.phpvms.net/) page.
[on the phpVMS documentation](http://docs.phpvms.net/) page.
# installation ## Installation
A full distribution, with all of the composer dependencies, is available at this A full distribution, with all of the composer dependencies, is available at this
[GitHub Releases](https://github.com/nabeelio/phpvms/releases) link. [GitHub Releases](https://github.com/nabeelio/phpvms/releases) link.
### Requirements
- PHP 7.3+, extensions:
## Requirements
- PHP 7.1+, extensions:
- cURL - cURL
- JSON - JSON
- mbstring - mbstring
@@ -24,16 +21,16 @@ A full distribution, with all of the composer dependencies, is available at this
- Database: - Database:
- MySQL 5.5+ (or MySQL variant, including MariaDB and Percona) - MySQL 5.5+ (or MySQL variant, including MariaDB and Percona)
[View more details on requirements](http://docs.phpvms.net/setup/requirements) [View more details on requirements](https://docs.phpvms.net/requirements)
## Installer ### Installer
1. Upload to your server 1. Upload to your server
1. Visit the site, and follow the link to the installer 1. Visit the site, and follow the link to the installer
[View installation details](http://docs.phpvms.net/setup/installation) [View installation details](https://docs.phpvms.net/installation/installation)
# development environment ## Development Environment
A full development environment can be brought up using Docker: A full development environment can be brought up using Docker:
@@ -50,7 +47,7 @@ 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
``` ```
## Building JS/CSS assets ### Building JS/CSS assets
Yarn is required, run: Yarn is required, run:
+13 -5
View File
@@ -79,21 +79,29 @@ class CreateDatabase extends Command
*/ */
protected function create_sqlite($dbkey) protected function create_sqlite($dbkey)
{ {
$dbPath = config($dbkey.'database');
// Skip if running in memory
if ($dbPath === ':memory:') {
return;
}
$exec = 'sqlite3'; $exec = 'sqlite3';
if ($this->os->isWindowsLike()) { if ($this->os->isWindowsLike()) {
$exec = 'sqlite3.exe'; $exec = 'sqlite3.exe';
} }
if ($this->option('reset') === true) { if ($this->option('reset') === true) {
$cmd = ['rm', '-rf', config($dbkey.'database')]; if (file_exists($dbPath)) {
$this->runCommand($cmd); unlink(config($dbkey.'database'));
}
} }
if (!file_exists(config($dbkey.'database'))) { if (!file_exists($dbPath)) {
$cmd = [ $cmd = [
$exec, $exec,
config($dbkey.'database'), $dbPath,
'""', '".exit"',
]; ];
$this->runCommand($cmd); $this->runCommand($cmd);
@@ -1,10 +1,10 @@
<?php <?php
namespace Modules\Importer\Console\Commands; namespace App\Console\Commands;
use App\Contracts\Command; use App\Contracts\Command;
use App\Services\ImporterService;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use Modules\Importer\Services\ImporterService;
class ImportFromClassicCommand extends Command class ImportFromClassicCommand extends Command
{ {
+15 -1
View File
@@ -3,7 +3,7 @@
namespace App\Console\Commands; namespace App\Console\Commands;
use App\Contracts\Command; use App\Contracts\Command;
use DB; use Illuminate\Support\Facades\DB;
use Symfony\Component\Yaml\Yaml; use Symfony\Component\Yaml\Yaml;
/** /**
@@ -25,6 +25,20 @@ class YamlExport extends Command
exit(); exit();
} }
// A "preset" for exporting the base set of data
if ($tables[0] === 'base') {
$tables = [
'airlines',
'aircraft',
'subfleets',
'subfleet_fare',
'subfleet_rank',
'bids',
'fares',
'flights',
];
}
$export_tables = []; $export_tables = [];
foreach ($tables as $table) { foreach ($tables as $table) {
$export_tables[$table] = []; $export_tables[$table] = [];
+3
View File
@@ -36,7 +36,10 @@ abstract class Award
* You don't really need to mess with anything below here * You don't really need to mess with anything below here
*/ */
/** @var \App\Models\Award|null */
protected $award; protected $award;
/** @var \App\Models\User|null */
protected $user; protected $user;
public function __construct(AwardModel $award = null, User $user = null) public function __construct(AwardModel $award = null, User $user = null)
+7 -6
View File
@@ -3,6 +3,7 @@
namespace App\Contracts; namespace App\Contracts;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use function is_array;
use Symfony\Component\Process\Process; use Symfony\Component\Process\Process;
/** /**
@@ -82,9 +83,9 @@ abstract class Command extends \Illuminate\Console\Command
} }
/** /**
* @param $cmd * @param array|string $cmd
* @param bool $return * @param bool $return
* @param mixed $verbose * @param mixed $verbose
* *
* @throws \Symfony\Component\Process\Exception\RuntimeException * @throws \Symfony\Component\Process\Exception\RuntimeException
* @throws \Symfony\Component\Process\Exception\LogicException * @throws \Symfony\Component\Process\Exception\LogicException
@@ -93,16 +94,16 @@ abstract class Command extends \Illuminate\Console\Command
*/ */
public function runCommand($cmd, $return = false, $verbose = true): string public function runCommand($cmd, $return = false, $verbose = true): string
{ {
if (\is_array($cmd)) { if (is_array($cmd)) {
$cmd = implode(' ', $cmd); $cmd = implode(' ', $cmd);
} }
if ($verbose) { if ($verbose) {
$this->info('Running "'.$cmd.'"'); $this->info('Running '.$cmd);
} }
$val = ''; $val = '';
$process = new Process($cmd); $process = Process::fromShellCommandline($cmd);
$process->run(function ($type, $buffer) use ($return, &$val) { $process->run(function ($type, $buffer) use ($return, &$val) {
if ($return) { if ($return) {
$val .= $buffer; $val .= $buffer;
+12
View File
@@ -0,0 +1,12 @@
<?php
namespace App\Contracts;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class Event
{
use Dispatchable;
use SerializesModels;
}
+4 -4
View File
@@ -3,9 +3,9 @@
namespace App\Contracts; namespace App\Contracts;
use App\Models\Airline; use App\Models\Airline;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\ValidationException; use Illuminate\Validation\ValidationException;
use Log;
use Validator;
/** /**
* Common functionality used across all of the importers * Common functionality used across all of the importers
@@ -51,9 +51,9 @@ class ImportExport
* *
* @param $code * @param $code
* *
* @return \Illuminate\Database\Eloquent\Model * @return Airline
*/ */
public function getAirline($code) public function getAirline($code): Airline
{ {
$airline = Airline::firstOrCreate([ $airline = Airline::firstOrCreate([
'icao' => $code, 'icao' => $code,
+1 -1
View File
@@ -16,7 +16,7 @@ abstract class Listener
public function subscribe(Dispatcher $events): void public function subscribe(Dispatcher $events): void
{ {
foreach (static::$callbacks as $klass => $cb) { foreach (static::$callbacks as $klass => $cb) {
$events->listen($klass, get_class($this).'@'.$cb); $events->listen($klass, static::class.'@'.$cb);
} }
} }
} }
+48 -3
View File
@@ -2,9 +2,13 @@
namespace App\Contracts; namespace App\Contracts;
use App\Models\Module;
use App\Support\Database; use App\Support\Database;
use DB; use Exception;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\ValidationException;
/** /**
* Class Migration * Class Migration
@@ -25,6 +29,29 @@ abstract class Migration extends \Illuminate\Database\Migrations\Migration
{ {
} }
/**
* Add a module and enable it
*
* @param array $attrs
*/
public function addModule(array $attrs)
{
$module = array_merge([
'enabled' => true,
'created_at' => DB::raw('NOW()'),
'updated_at' => DB::raw('NOW()'),
], $attrs);
try {
DB::table('modules')->insert($module);
} catch (Exception $e) {
// setting already exists, just ignore it
if ($e->getCode() === 23000) {
return;
}
}
}
/** /**
* Seed a YAML file into the database * Seed a YAML file into the database
* *
@@ -35,7 +62,7 @@ abstract class Migration extends \Illuminate\Database\Migrations\Migration
try { try {
$path = base_path($file); $path = base_path($file);
Database::seed_from_yaml_file($path, false); Database::seed_from_yaml_file($path, false);
} catch (\Exception $e) { } catch (Exception $e) {
Log::error('Unable to load '.$file.' file'); Log::error('Unable to load '.$file.' file');
Log::error($e); Log::error($e);
} }
@@ -52,7 +79,7 @@ abstract class Migration extends \Illuminate\Database\Migrations\Migration
foreach ($rows as $row) { foreach ($rows as $row) {
try { try {
DB::table($table)->insert($row); DB::table($table)->insert($row);
} catch (\Exception $e) { } catch (Exception $e) {
// setting already exists, just ignore it // setting already exists, just ignore it
if ($e->getCode() === 23000) { if ($e->getCode() === 23000) {
continue; continue;
@@ -60,4 +87,22 @@ abstract class Migration extends \Illuminate\Database\Migrations\Migration
} }
} }
} }
/**
* Add an award from the migrations (for example, if you're adding an award module)
*
* @param array $award See \App\Models\Awardv
*
* @throws \Illuminate\Validation\ValidationException
*/
public function addAward(array $award)
{
$validator = Validator::make($award, \App\Models\Award::$rules);
if ($validator->fails()) {
throw new ValidationException($validator);
}
$awardModel = new \App\Models\Award($award);
$awardModel->save();
}
} }
+49
View File
@@ -0,0 +1,49 @@
<?php
namespace App\Contracts\Modules;
/**
* Base class for module service providers
* Add-on module service providers must extend this class. Docs on Service Providers:
* https://laravel.com/docs/7.x/providers
*
* For a sample service provider, view the sample module one:
* https://github.com/nabeelio/phpvms-module/blob/master/Providers/SampleServiceProvider.php
*/
abstract class ServiceProvider extends \Illuminate\Support\ServiceProvider
{
/**
* A boot method is required, even if it doesn't do anything.
* https://laravel.com/docs/7.x/providers#the-boot-method
*
* This is normally where you'd register the routes or other startup tasks for your module
*/
public function boot(): void
{
}
/**
* This is required to register the links in either the public or admin toolbar
* For example, adding a frontend link:
*
* $this->moduleSvc->addFrontendLink('Sample', '/sample', '', $logged_in=true);
*
* Or an admin link:
*
* $this->moduleSvc->addAdminLink('Sample', '/admin/sample');
*/
public function registerLinks(): void
{
}
/**
* Deferred providers:
* https://laravel.com/docs/7.x/providers#deferred-providers
*
* @return array
*/
public function provides(): array
{
return [];
}
}
@@ -1,23 +1,23 @@
<?php <?php
namespace App\Notifications; namespace App\Contracts;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Notification;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
class BaseNotification extends Notification implements ShouldQueue class Notification extends \Illuminate\Notifications\Notification implements ShouldQueue
{ {
use Queueable; use Queueable;
public $channels = []; public $channels = [];
public $requires_opt_in = false;
public function __construct() public function __construct()
{ {
// 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 = get_class($this); $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');
+3 -1
View File
@@ -2,10 +2,12 @@
namespace App\Contracts; namespace App\Contracts;
use Illuminate\Http\Resources\Json\JsonResource;
/** /**
* Base class for a resource/response * Base class for a resource/response
*/ */
class Resource extends \Illuminate\Http\Resources\Json\Resource class Resource extends JsonResource
{ {
/** /**
* Iterate through the list of $fields and check if they're a "Unit" * Iterate through the list of $fields and check if they're a "Unit"
+11 -5
View File
@@ -1,24 +1,30 @@
<?php <?php
use App\Models\Airport;
use App\Models\Enums\AircraftState;
use App\Models\Enums\AircraftStatus;
use App\Models\Subfleet;
use App\Support\ICAO;
use Faker\Generator as Faker; use Faker\Generator as Faker;
$factory->define(App\Models\Aircraft::class, function (Faker $faker) { $factory->define(App\Models\Aircraft::class, function (Faker $faker) {
return [ return [
'id' => null, 'id' => null,
'subfleet_id' => function () { 'subfleet_id' => function () {
return factory(App\Models\Subfleet::class)->create()->id; return factory(Subfleet::class)->create()->id;
}, },
'airport_id' => function () { 'airport_id' => function () {
return factory(App\Models\Airport::class)->create()->id; return factory(Airport::class)->create()->id;
}, },
'iata' => $faker->unique()->text(5), 'iata' => $faker->unique()->text(5),
'icao' => $faker->unique()->text(5), 'icao' => $faker->unique()->text(5),
'name' => $faker->text(50), 'name' => $faker->text(50),
'registration' => $faker->unique()->text(10), 'registration' => $faker->unique()->text(10),
'hex_code' => \App\Support\ICAO::createHexCode(), 'hex_code' => ICAO::createHexCode(),
'mtow' => $faker->randomFloat(2, 0, 50000),
'zfw' => $faker->randomFloat(2, 0, 50000), 'zfw' => $faker->randomFloat(2, 0, 50000),
'status' => \App\Models\Enums\AircraftStatus::ACTIVE, 'status' => AircraftStatus::ACTIVE,
'state' => \App\Models\Enums\AircraftState::PARKED, 'state' => AircraftState::PARKED,
'created_at' => $faker->dateTimeBetween('-1 week', 'now'), 'created_at' => $faker->dateTimeBetween('-1 week', 'now'),
'updated_at' => function (array $pirep) { 'updated_at' => function (array $pirep) {
return $pirep['created_at']; return $pirep['created_at'];
+1 -1
View File
@@ -9,7 +9,7 @@ use Hashids\Hashids;
$factory->define(App\Models\Airline::class, function (Faker $faker) { $factory->define(App\Models\Airline::class, function (Faker $faker) {
return [ return [
'id' => null, 'id' => null,
'icao' => function (array $apt) use ($faker) { 'icao' => function (array $apt) {
$hashids = new Hashids(microtime(), 5); $hashids = new Hashids(microtime(), 5);
$mt = str_replace('.', '', microtime(true)); $mt = str_replace('.', '', microtime(true));
+4 -4
View File
@@ -8,19 +8,19 @@ $factory->define(App\Models\Flight::class, function (Faker $faker) {
return [ return [
'id' => $faker->unique()->numberBetween(10, 10000000), 'id' => $faker->unique()->numberBetween(10, 10000000),
'airline_id' => function () { 'airline_id' => function () {
return factory(App\Models\Airline::class)->create()->id; return factory(\App\Models\Airline::class)->create()->id;
}, },
'flight_number' => $faker->unique()->numberBetween(10, 1000000), 'flight_number' => $faker->unique()->numberBetween(10, 1000000),
'route_code' => $faker->randomElement(['', $faker->text(5)]), 'route_code' => $faker->randomElement(['', $faker->text(5)]),
'route_leg' => $faker->randomElement(['', $faker->numberBetween(0, 1000)]), 'route_leg' => $faker->randomElement(['', $faker->numberBetween(0, 1000)]),
'dpt_airport_id' => function () { 'dpt_airport_id' => function () {
return factory(App\Models\Airport::class)->create()->id; return factory(\App\Models\Airport::class)->create()->id;
}, },
'arr_airport_id' => function () { 'arr_airport_id' => function () {
return factory(App\Models\Airport::class)->create()->id; return factory(\App\Models\Airport::class)->create()->id;
}, },
'alt_airport_id' => function () { 'alt_airport_id' => function () {
return factory(App\Models\Airport::class)->create()->id; return factory(\App\Models\Airport::class)->create()->id;
}, },
'distance' => $faker->numberBetween(1, 1000), 'distance' => $faker->numberBetween(1, 1000),
'route' => null, 'route' => null,
@@ -6,7 +6,7 @@ $factory->define(App\Models\JournalTransactions::class, function (Faker $faker)
return [ return [
'transaction_group' => \Ramsey\Uuid\Uuid::uuid4()->toString(), 'transaction_group' => \Ramsey\Uuid\Uuid::uuid4()->toString(),
'journal_id' => function () { 'journal_id' => function () {
return factory(App\Models\Journal::class)->create()->id; return factory(\App\Models\Journal::class)->create()->id;
}, },
'credit' => $faker->numberBetween(100, 10000), 'credit' => $faker->numberBetween(100, 10000),
'debit' => $faker->numberBetween(100, 10000), 'debit' => $faker->numberBetween(100, 10000),
+1 -1
View File
@@ -6,7 +6,7 @@ $factory->define(App\Models\News::class, function (Faker $faker) {
return [ return [
'id' => null, 'id' => null,
'user_id' => function () { 'user_id' => function () {
return factory(App\Models\User::class)->create()->id; return factory(\App\Models\User::class)->create()->id;
}, },
'subject' => $faker->text(), 'subject' => $faker->text(),
'body' => $faker->sentence, 'body' => $faker->sentence,
+4 -4
View File
@@ -10,8 +10,8 @@ use Faker\Generator as Faker;
* Create a new PIREP * Create a new PIREP
*/ */
$factory->define(App\Models\Pirep::class, function (Faker $faker) { $factory->define(App\Models\Pirep::class, function (Faker $faker) {
$airline = factory(App\Models\Airline::class)->create(); $airline = factory(\App\Models\Airline::class)->create();
$flight = factory(App\Models\Flight::class)->create([ $flight = factory(\App\Models\Flight::class)->create([
'airline_id' => $airline->id, 'airline_id' => $airline->id,
]); ]);
@@ -21,10 +21,10 @@ $factory->define(App\Models\Pirep::class, function (Faker $faker) {
return $airline->id; return $airline->id;
}, },
'user_id' => function () { 'user_id' => function () {
return factory(App\Models\User::class)->create()->id; return factory(\App\Models\User::class)->create()->id;
}, },
'aircraft_id' => function () { 'aircraft_id' => function () {
return factory(App\Models\Aircraft::class)->create()->id; return factory(\App\Models\Aircraft::class)->create()->id;
}, },
'flight_id' => function () use ($flight) { 'flight_id' => function () use ($flight) {
return $flight->id; return $flight->id;
+1 -1
View File
@@ -6,7 +6,7 @@ $factory->define(App\Models\Subfleet::class, function (Faker $faker) {
return [ return [
'id' => null, 'id' => null,
'airline_id' => function () { 'airline_id' => function () {
return factory(App\Models\Airline::class)->create()->id; return factory(\App\Models\Airline::class)->create()->id;
}, },
'name' => $faker->unique()->text(50), 'name' => $faker->unique()->text(50),
'type' => $faker->unique()->text(7), 'type' => $faker->unique()->text(7),
+3 -1
View File
@@ -1,7 +1,9 @@
<?php <?php
use App\Models\Airline;
use App\Models\Enums\UserState; use App\Models\Enums\UserState;
use Faker\Generator as Faker; use Faker\Generator as Faker;
use Illuminate\Support\Facades\Hash;
$factory->define(App\Models\User::class, function (Faker $faker) { $factory->define(App\Models\User::class, function (Faker $faker) {
static $password; static $password;
@@ -14,7 +16,7 @@ $factory->define(App\Models\User::class, function (Faker $faker) {
'password' => $password ?: $password = Hash::make('secret'), 'password' => $password ?: $password = Hash::make('secret'),
'api_key' => $faker->sha1, 'api_key' => $faker->sha1,
'airline_id' => function () { 'airline_id' => function () {
return factory(App\Models\Airline::class)->create()->id; return factory(Airline::class)->create()->id;
}, },
'rank_id' => 1, 'rank_id' => 1,
'flights' => $faker->numberBetween(0, 1000), 'flights' => $faker->numberBetween(0, 1000),
@@ -3,12 +3,15 @@
use App\Contracts\Migration; use App\Contracts\Migration;
use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema; use Illuminate\Support\Facades\Schema;
use Modules\Awards\Awards\PilotFlightAwards;
class CreateAwardsTable extends Migration class CreateAwardsTable extends Migration
{ {
/** /**
* Run the migrations. * Run the migrations.
* *
* @throws \Illuminate\Validation\ValidationException
*
* @return void * @return void
*/ */
public function up() public function up()
@@ -23,7 +26,6 @@ class CreateAwardsTable extends Migration
// EG, the airports has an internal expense for gate costs // EG, the airports has an internal expense for gate costs
$table->string('ref_model')->nullable(); $table->string('ref_model')->nullable();
$table->text('ref_model_params')->nullable(); $table->text('ref_model_params')->nullable();
//$table->string('ref_model_id', 36)->nullable();
$table->timestamps(); $table->timestamps();
@@ -38,6 +40,18 @@ class CreateAwardsTable extends Migration
$table->index(['user_id', 'award_id']); $table->index(['user_id', 'award_id']);
}); });
/**
* Add a default, sample award
*/
$award = [
'name' => 'Pilot 50 flights',
'description' => 'When a pilot has 50 flights, give this award',
'ref_model' => PilotFlightAwards::class,
'ref_model_params' => 50,
];
$this->addAward($award);
} }
/** /**
@@ -1,5 +1,6 @@
<?php <?php
use App\Models\Enums\PageType;
use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema; use Illuminate\Support\Facades\Schema;
@@ -22,7 +23,7 @@ class CreatePages extends Migration
$table->string('name'); $table->string('name');
$table->string('slug'); $table->string('slug');
$table->string('icon'); $table->string('icon');
$table->unsignedSmallInteger('type'); $table->unsignedSmallInteger('type')->default(PageType::PAGE);
$table->boolean('public'); $table->boolean('public');
$table->boolean('enabled'); $table->boolean('enabled');
$table->mediumText('body'); $table->mediumText('body');
@@ -0,0 +1,36 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class PagesAddLink extends Migration
{
/**
* Add a `link` column and make the body optional. Also add a "new_window" bool
* which determines if we open this link in a new window or not
*/
public function up()
{
Schema::table('pages', function (Blueprint $table) {
$table->string('body')->change()->nullable();
$table->string('link')
->default('')
->nullable()
->after('body');
$table->boolean('new_window')->default(false);
});
}
/**
* @return void
*/
public function down()
{
Schema::table('fares', function (Blueprint $table) {
$table->dropColumn('link');
$table->dropColumn('new_window');
});
}
}
@@ -0,0 +1,49 @@
<?php
use App\Contracts\Model;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateUserFields extends Migration
{
/**
* Add two tables for holding user fields and the values
*/
public function up()
{
/*
* Hold a master list of fields
*/
Schema::create('user_fields', function (Blueprint $table) {
$table->increments('id');
$table->string('name', 200);
$table->text('description')->nullable();
$table->boolean('show_on_registration')->default(false)->nullable();
$table->boolean('required')->default(false)->nullable();
$table->boolean('private')->default(false)->nullable();
$table->boolean('active')->default(true)->nullable();
$table->timestamps();
});
/*
* The values for the actual fields
*/
Schema::create('user_field_values', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('user_field_id');
$table->string('user_id', Model::ID_MAX_LENGTH);
$table->text('value')->nullable();
$table->timestamps();
$table->index(['user_field_id', 'user_id']);
});
}
/**
* @return void
*/
public function down()
{
}
}
@@ -0,0 +1,33 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
/**
* Add a `mtow` column for the max takeoff weight
*/
class AircraftAddMtow extends Migration
{
public function up()
{
Schema::table('aircraft', function (Blueprint $table) {
$table->unsignedDecimal('mtow')
->nullable()
->default(0.0)
->after('hex_code');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('aircraft', function (Blueprint $table) {
$table->dropColumn('mtow');
});
}
}
@@ -0,0 +1,39 @@
<?php
use App\Contracts\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateModulesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('modules', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->boolean('enabled')->default(1);
$table->timestamps();
});
$this->addModule(['name' => 'Awards']);
$this->addModule(['name' => 'Sample']);
$this->addModule(['name' => 'VMSAcars']);
$this->addModule(['name' => 'Vacentral']);
$this->addModule(['name' => 'TestModule']);
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('modules');
}
}
+15 -3
View File
@@ -1,15 +1,21 @@
<?php <?php
use App\Services\Installer\MigrationService;
use App\Services\Installer\SeederService; use App\Services\Installer\SeederService;
use Illuminate\Database\Seeder; use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder class DatabaseSeeder extends Seeder
{ {
private $seederService; /** @var MigrationService */
private $migrationSvc;
/** @var SeederService */
private $seederSvc;
public function __construct() public function __construct()
{ {
$this->seederService = app(SeederService::class); $this->migrationSvc = app(MigrationService::class);
$this->seederSvc = app(SeederService::class);
} }
/** /**
@@ -19,6 +25,12 @@ class DatabaseSeeder extends Seeder
*/ */
public function run() public function run()
{ {
$this->seederService->syncAllSeeds(); // Make sure any migrations that need to be run are run/cleared out
if ($this->migrationSvc->migrationsAvailable()) {
$this->migrationSvc->runAllMigrations();
}
// Then sync all of the seeds
$this->seederSvc->syncAllSeeds();
} }
} }
+1
View File
@@ -1 +1,2 @@
local.yml local.yml
vmsacars.yml
+8
View File
@@ -12,3 +12,11 @@ airlines:
active: 1 active: 1
created_at: now created_at: now
updated_at: now updated_at: now
- id: 2
icao: XXX
iata: XX
name: inactive airline
country: us
active: 0
created_at: now
updated_at: now
+275 -73
View File
@@ -1,30 +1,10 @@
#airlines:
# - id: 1
# icao: VMS
# iata: VM
# name: phpvms airlines
# country: us
# active: 1
# created_at: now
# updated_at: now
roles: roles:
id_column: name id_column: name
data: data:
- name: fleet-only - name: fleet-only
display_name: Edit Fleet display_name: Edit Fleet
awards:
- id: 1
name: Pilot 50 flights
description: When a pilot has 50 flights, give this award
image_url:
ref_model: Modules\Awards\Awards\PilotFlightAwards
ref_model_params: 50
created_at: now
updated_at: now
news: news:
- id: 1 - id: 1
user_id: 1 user_id: 1
@@ -136,34 +116,91 @@ airports:
ground_handling_cost: 50 ground_handling_cost: 50
# #
aircraft: aircraft:
- id: 1 -
id: 1
subfleet_id: 1 subfleet_id: 1
icao: null
iata: null
airport_id: KJFK airport_id: KJFK
name: Boeing 747-438 landing_time: '2020-10-23 07:50:16'
name: 'Boeing 747-438'
registration: 001Z registration: 001Z
flight_time: 360 hex_code: null
mtow: '0.00'
zfw: '0.00'
flight_time: 540
status: A status: A
- id: 2 state: 0
created_at: null
updated_at: '2020-10-23 07:50:16'
-
id: 2
subfleet_id: 2 subfleet_id: 2
icao: null
iata: null
airport_id: LGRP airport_id: LGRP
name: Boeing 777-200 landing_time: null
name: 'Boeing 777-200'
registration: C202 registration: C202
hex_code: null
mtow: '0.00'
zfw: '0.00'
flight_time: 260 flight_time: 260
status: A status: A
- id: 3 state: 0
created_at: null
updated_at: null
-
id: 3
subfleet_id: 1 subfleet_id: 1
icao: null
iata: null
airport_id: KAUS airport_id: KAUS
name: Boeing 747-412 landing_time: '2020-10-24 08:50:13'
name: 'Boeing 747-412'
registration: S2333 registration: S2333
flight_time: 0 hex_code: null
mtow: '0.00'
zfw: '0.00'
flight_time: 180
status: A status: A
- id: 4 state: 0
created_at: null
updated_at: '2020-10-24 08:50:13'
-
id: 4
subfleet_id: 1 subfleet_id: 1
icao: null
iata: null
airport_id: KAUS airport_id: KAUS
name: Boeing 747-436 RETIRED landing_time: null
registration: name: 'Boeing 747-436 RETIRED'
registration: null
hex_code: null
mtow: '0.00'
zfw: '0.00'
flight_time: 45 flight_time: 45
status: R status: R
state: 0
created_at: null
updated_at: null
-
id: 5
subfleet_id: 4
icao: A320
iata: '320'
airport_id: EGLL
landing_time: null
name: 'Airbus A320'
registration: N786DL
hex_code: b47165dd
mtow: '78800.00'
zfw: '62500.00'
flight_time: 0
status: A
state: 0
created_at: '2020-10-22 13:38:50'
updated_at: '2020-10-22 13:38:50'
expenses: expenses:
- name: Per-Flight (no muliplier) - name: Per-Flight (no muliplier)
@@ -220,68 +257,192 @@ expenses:
updated_at: now updated_at: now
fares: fares:
- id: 1 -
code: Y id: 1
code: 'Y'
name: Economy name: Economy
price: 100 price: '100.00'
cost: '0.00'
capacity: 200 capacity: 200
- id: 2 type: 0
notes: null
active: 1
created_at: null
updated_at: null
-
id: 2
code: B code: B
name: Business name: Business
price: 500 price: '500.00'
cost: '0.00'
capacity: 10 capacity: 10
- id: 3 type: 0
notes: null
active: 1
created_at: null
updated_at: null
-
id: 3
code: F code: F
name: First-Class name: First-Class
price: 800 price: '800.00'
cost: '0.00'
capacity: 5 capacity: 5
type: 0
notes: null
active: 1
created_at: null
updated_at: null
subfleets: subfleets:
- id: 1 -
id: 1
airline_id: 1 airline_id: 1
name: 747-43X RB211-524G
type: 744-3X-RB211 type: 744-3X-RB211
cost_block_hour: 1000 name: '747-43X RB211-524G'
ground_handling_multiplier: 200 cost_block_hour: '1000.00'
- id: 2 cost_delay_minute: '0.00'
fuel_type: null
ground_handling_multiplier: '200.00'
cargo_capacity: null
fuel_capacity: null
gross_weight: null
created_at: null
updated_at: null
-
id: 2
airline_id: 1 airline_id: 1
name: 777-222ER GE90-76B
type: 772-22ER-GE90-76B type: 772-22ER-GE90-76B
cost_block_hour: 500 name: '777-222ER GE90-76B'
ground_handling_multiplier: 150 cost_block_hour: '500.00'
- id: 3 cost_delay_minute: '0.00'
fuel_type: null
ground_handling_multiplier: '150.00'
cargo_capacity: null
fuel_capacity: null
gross_weight: null
created_at: null
updated_at: null
-
id: 3
airline_id: 1 airline_id: 1
name: 777-367 ER GE90-115B
type: 772-36ER-GE90-115B type: 772-36ER-GE90-115B
cost_block_hour: 100 name: '777-367 ER GE90-115B'
ground_handling_multiplier: 150 cost_block_hour: '100.00'
cost_delay_minute: '0.00'
fuel_type: null
ground_handling_multiplier: '150.00'
cargo_capacity: null
fuel_capacity: null
gross_weight: null
created_at: null
updated_at: null
-
id: 4
airline_id: 1
type: A320
name: A320
cost_block_hour: '2300.00'
cost_delay_minute: null
fuel_type: 1
ground_handling_multiplier: '100.00'
cargo_capacity: null
fuel_capacity: null
gross_weight: null
created_at: '2020-10-22 13:36:49'
updated_at: '2020-10-22 13:36:49'
# add a few mods to aircraft and fares
subfleet_fare: subfleet_fare:
-
# Fare classes on the 747 subfleet_id: 1
- subfleet_id: 1
fare_id: 1 fare_id: 1
price: 200 price: '200'
capacity: 400 cost: null
- subfleet_id: 1 capacity: '400'
created_at: null
updated_at: null
-
subfleet_id: 1
fare_id: 2 fare_id: 2
price: 120% price: 120%
- subfleet_id: 1 cost: null
fare_id: 3 capacity: null
price: 1000 created_at: null
capacity: 110% updated_at: null
-
# Fare classes on the 777
- subfleet_id: 2
fare_id: 1
- subfleet_id: 2
fare_id: 3
capacity: 10
subfleet_rank:
- rank_id: 1
subfleet_id: 1 subfleet_id: 1
fare_id: 3
price: '1000'
cost: null
capacity: 110%
created_at: null
updated_at: null
-
subfleet_id: 2
fare_id: 1
price: null
cost: null
capacity: null
created_at: null
updated_at: null
-
subfleet_id: 2
fare_id: 3
price: null
cost: null
capacity: '10'
created_at: null
updated_at: null
-
subfleet_id: 4
fare_id: 1
price: null
cost: null
capacity: '123'
created_at: null
updated_at: null
-
subfleet_id: 4
fare_id: 2
price: null
cost: null
capacity: '8'
created_at: null
updated_at: null
-
subfleet_id: 4
fare_id: 3
price: null
cost: null
capacity: '2'
created_at: null
updated_at: null
subfleet_rank:
-
rank_id: 1
subfleet_id: 1
acars_pay: null
manual_pay: null
-
rank_id: 1
subfleet_id: 4
acars_pay: null
manual_pay: null
-
rank_id: 2
subfleet_id: 4
acars_pay: null
manual_pay: null
-
rank_id: 3
subfleet_id: 4
acars_pay: null
manual_pay: null
-
rank_id: 4
subfleet_id: 4
acars_pay: null
manual_pay: null
flights: flights:
- id: flightid_1 - id: flightid_1
@@ -359,6 +520,35 @@ flights:
route: 'MLY5 KEMBO UG442 SIA UG633 OTEKO UR640 NALRO GUBEL3' route: 'MLY5 KEMBO UG442 SIA UG633 OTEKO UR640 NALRO GUBEL3'
created_at: NOW created_at: NOW
updated_at: NOW updated_at: NOW
-
id: q8mvZ5vdExoy0mQG
airline_id: 1
flight_number: 3003
route_code: null
route_leg: null
dpt_airport_id: KSEA
arr_airport_id: KPAE
alt_airport_id: null
dpt_time: '8:00'
arr_time: '8:45'
level: null
distance: '27.51'
flight_time: 45
flight_type: J
load_factor: null
load_factor_variance: null
route: null
pilot_pay: null
notes: null
scheduled: 0
days: null
start_date: null
end_date: null
has_bid: 1
active: 1
visible: 1
created_at: now
updated_at: now
flight_fields: flight_fields:
- name: Departure Terminal - name: Departure Terminal
@@ -389,12 +579,24 @@ flight_subfleet:
flight_id: flightid_4 flight_id: flightid_4
bids: bids:
- id: 100 -
id: 100
user_id: 1 user_id: 1
flight_id: flightid_1 flight_id: flightid_1
- id: 101 created_at: now
updated_at: now
-
id: 101
user_id: 1 user_id: 1
flight_id: flightid_3 flight_id: flightid_3
created_at: now
updated_at: now
-
id: 102
user_id: 1
flight_id: q8mvZ5vdExoy0mQG
created_at: now
updated_at: now
pireps: pireps:
- id: pirepid_1 - id: pirepid_1
+30
View File
@@ -69,3 +69,33 @@ role_user:
- user_id: 3 - user_id: 3
role_id: 2 role_id: 2
user_type: App\Models\User user_type: App\Models\User
user_fields:
- id: 1
name: 'VATSIM ID'
show_on_registration: true
required: false
private: false
- id: 2
name: 'Referral'
description: 'Who referred you'
show_on_registration: true
required: false
private: true
user_field_values:
- id: 1
user_field_id: 1
user_id: 1
value: 'my vatsim id'
- id: 2
user_field_id: 2
user_id: 1
value: 'Nobody did'
user_awards:
- id: 1
user_id: 1
award_id: 1
created_at: now
updated_at: now
+10
View File
@@ -0,0 +1,10 @@
- name: 'Awards'
enabled: 1
- name: 'Sample'
enabled: 1
- name: 'VMSAcars'
enabled: 1
- name: 'Vacentral'
enabled: 1
- name: 'TestModule'
enabled: 1
+6
View File
@@ -3,6 +3,9 @@
- name: admin-access - name: admin-access
display_name: Admin Panel display_name: Admin Panel
description: Access the admin panel description: Access the admin panel
- name: aircraft
display_name: Aircraft
description: Create/edit aircraft
- name: airlines - name: airlines
display_name: Airlines display_name: Airlines
description: Create/edit airlines description: Create/edit airlines
@@ -48,3 +51,6 @@
- name: maintenance - name: maintenance
display_name: Maintenance display_name: Maintenance
description: Run maintenance tasks description: Run maintenance tasks
- name: modules
display_name: Modules
description: Add/Edit Modules
+21
View File
@@ -26,6 +26,13 @@
options: options:
type: boolean type: boolean
description: If an airport isn't added, try to look it up when adding schedules description: If an airport isn't added, try to look it up when adding schedules
- key: general.allow_unadded_airports
name: 'Allow unadded airports'
group: general
value: false
options:
type: boolean
description: If an un-added airport is used, it is looked up and added
- key: general.check_prerelease_version - key: general.check_prerelease_version
name: 'Pre-release versions in version check' name: 'Pre-release versions in version check'
group: general group: general
@@ -123,6 +130,20 @@
options: '' options: ''
type: int type: int
description: 'Initial zoom level on the map' description: 'Initial zoom level on the map'
- key: airports.default_ground_handling_cost
name: 'Default Ground Handling Cost'
group: airports
value: 250
options:
type: int
description: If an airport's Ground Handling Cost Cost isn't added, set this value by default
- key: airports.default_jet_a_fuel_cost
name: 'Default Jet A Fuel Cost'
group: airports
value: 0.7
options:
type: text
description: If an airport's Jet A 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
+22
View File
@@ -0,0 +1,22 @@
<?php
namespace App\Events;
use App\Contracts\Event;
use App\Models\Acars;
use App\Models\Pirep;
class AcarsUpdate extends Event
{
/** @var Pirep */
public $pirep;
/** @var Acars */
public $acars;
public function __construct(Pirep $pirep, Acars $acars)
{
$this->pirep = $pirep;
$this->acars = $acars;
}
}
+5 -7
View File
@@ -2,13 +2,11 @@
namespace App\Events; namespace App\Events;
use Illuminate\Broadcasting\InteractsWithSockets; use App\Contracts\Event;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class BaseEvent /**
* @deprecated Extend App\Contracts\Event directly
*/
class BaseEvent extends Event
{ {
use Dispatchable;
use InteractsWithSockets;
use SerializesModels;
} }
+3 -1
View File
@@ -2,6 +2,8 @@
namespace App\Events; namespace App\Events;
class CronHourly extends BaseEvent use App\Contracts\Event;
class CronHourly extends Event
{ {
} }
+3 -1
View File
@@ -2,10 +2,12 @@
namespace App\Events; namespace App\Events;
use App\Contracts\Event;
/** /**
* This event is dispatched when the monthly cron is run * This event is dispatched when the monthly cron is run
* It happens after all of the default nightly tasks * It happens after all of the default nightly tasks
*/ */
class CronMonthly extends BaseEvent class CronMonthly extends Event
{ {
} }
+3 -1
View File
@@ -2,10 +2,12 @@
namespace App\Events; namespace App\Events;
use App\Contracts\Event;
/** /**
* This event is dispatched when the daily cron is run * This event is dispatched when the daily cron is run
* It happens after all of the default nightly tasks * It happens after all of the default nightly tasks
*/ */
class CronNightly extends BaseEvent class CronNightly extends Event
{ {
} }
+3 -1
View File
@@ -2,11 +2,13 @@
namespace App\Events; namespace App\Events;
use App\Contracts\Event;
/** /**
* This event is dispatched when the weekly cron is run * This event is dispatched when the weekly cron is run
* It happens after all of the default nightly tasks * It happens after all of the default nightly tasks
*/ */
class CronWeekly extends BaseEvent class CronWeekly extends Event
{ {
public function __construct() public function __construct()
{ {
+2 -1
View File
@@ -2,6 +2,7 @@
namespace App\Events; namespace App\Events;
use App\Contracts\Event;
use App\Models\Pirep; use App\Models\Pirep;
/** /**
@@ -25,7 +26,7 @@ use App\Models\Pirep;
* *
* The event will have a copy of the PIREP model, if it's applicable * The event will have a copy of the PIREP model, if it's applicable
*/ */
class Expenses extends BaseEvent class Expenses extends Event
{ {
public $pirep; public $pirep;
+2 -1
View File
@@ -2,9 +2,10 @@
namespace App\Events; namespace App\Events;
use App\Contracts\Event;
use App\Models\News; use App\Models\News;
class NewsAdded extends BaseEvent class NewsAdded extends Event
{ {
public $news; public $news;
+2 -1
View File
@@ -2,9 +2,10 @@
namespace App\Events; namespace App\Events;
use App\Contracts\Event;
use App\Models\Pirep; use App\Models\Pirep;
class PirepAccepted extends BaseEvent class PirepAccepted extends Event
{ {
public $pirep; public $pirep;
+2 -1
View File
@@ -2,9 +2,10 @@
namespace App\Events; namespace App\Events;
use App\Contracts\Event;
use App\Models\Pirep; use App\Models\Pirep;
class PirepCancelled extends BaseEvent class PirepCancelled extends Event
{ {
public $pirep; public $pirep;
+2 -1
View File
@@ -2,9 +2,10 @@
namespace App\Events; namespace App\Events;
use App\Contracts\Event;
use App\Models\Pirep; use App\Models\Pirep;
class PirepFiled extends BaseEvent class PirepFiled extends Event
{ {
public $pirep; public $pirep;
+2 -1
View File
@@ -2,9 +2,10 @@
namespace App\Events; namespace App\Events;
use App\Contracts\Event;
use App\Models\Pirep; use App\Models\Pirep;
class PirepPrefiled extends BaseEvent class PirepPrefiled extends Event
{ {
public $pirep; public $pirep;
+2 -1
View File
@@ -2,9 +2,10 @@
namespace App\Events; namespace App\Events;
use App\Contracts\Event;
use App\Models\Pirep; use App\Models\Pirep;
class PirepRejected extends BaseEvent class PirepRejected extends Event
{ {
public $pirep; public $pirep;
+2 -1
View File
@@ -2,9 +2,10 @@
namespace App\Events; namespace App\Events;
use App\Contracts\Event;
use App\Models\Pirep; use App\Models\Pirep;
class PirepUpdated extends BaseEvent class PirepUpdated extends Event
{ {
public $pirep; public $pirep;
+2 -1
View File
@@ -2,9 +2,10 @@
namespace App\Events; namespace App\Events;
use App\Contracts\Event;
use App\Models\User; use App\Models\User;
class TestEvent extends BaseEvent class TestEvent extends Event
{ {
public $user; public $user;
+2 -1
View File
@@ -2,9 +2,10 @@
namespace App\Events; namespace App\Events;
use App\Contracts\Event;
use App\Models\User; use App\Models\User;
class UserAccepted extends BaseEvent class UserAccepted extends Event
{ {
public $user; public $user;
+2 -1
View File
@@ -2,9 +2,10 @@
namespace App\Events; namespace App\Events;
use App\Contracts\Event;
use App\Models\User; use App\Models\User;
class UserRegistered extends BaseEvent class UserRegistered extends Event
{ {
public $user; public $user;
+2 -1
View File
@@ -2,12 +2,13 @@
namespace App\Events; namespace App\Events;
use App\Contracts\Event;
use App\Models\User; use App\Models\User;
/** /**
* Event triggered when a user's state changes * Event triggered when a user's state changes
*/ */
class UserStateChanged extends BaseEvent class UserStateChanged extends Event
{ {
public $old_state; public $old_state;
public $user; public $user;
+2 -1
View File
@@ -2,9 +2,10 @@
namespace App\Events; namespace App\Events;
use App\Contracts\Event;
use App\Models\User; use App\Models\User;
class UserStatsChanged extends BaseEvent class UserStatsChanged extends Event
{ {
public $stat_name; public $stat_name;
public $old_value; public $old_value;
+47
View File
@@ -0,0 +1,47 @@
<?php
namespace App\Exceptions;
use App\Models\Aircraft;
class AircraftInvalid extends AbstractHttpException
{
public const MESSAGE = 'The supplied aircraft is invalid';
private $aircraft;
public function __construct(Aircraft $aircraft)
{
$this->aircraft = $aircraft;
parent::__construct(
400,
static::MESSAGE
);
}
/**
* Return the RFC 7807 error type (without the URL root)
*/
public function getErrorType(): string
{
return 'aircraft-invalid';
}
/**
* 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 [
'aircraft_id' => optional($this->aircraft)->id,
];
}
}
@@ -3,13 +3,13 @@
namespace App\Exceptions\Converters; namespace App\Exceptions\Converters;
use App\Exceptions\AbstractHttpException; use App\Exceptions\AbstractHttpException;
use Exception; use Throwable;
class GenericExceptionAbstract extends AbstractHttpException class GenericExceptionAbstract extends AbstractHttpException
{ {
private $exception; private $exception;
public function __construct(Exception $exception) public function __construct(Throwable $exception)
{ {
$this->exception = $exception; $this->exception = $exception;
parent::__construct( parent::__construct(
@@ -18,7 +18,7 @@ class ValidationException extends AbstractHttpException
parent::__construct( parent::__construct(
400, 400,
'Validation exception' 'Validation Error'
); );
} }
+10 -37
View File
@@ -5,8 +5,7 @@ namespace App\Exceptions;
use App\Exceptions\Converters\GenericExceptionAbstract; use App\Exceptions\Converters\GenericExceptionAbstract;
use App\Exceptions\Converters\SymfonyException; use App\Exceptions\Converters\SymfonyException;
use App\Exceptions\Converters\ValidationException; use App\Exceptions\Converters\ValidationException;
use Exception; use App\Http\Middleware\SetActiveTheme;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Auth\AuthenticationException; use Illuminate\Auth\AuthenticationException;
use Illuminate\Contracts\Container\BindingResolutionException; use Illuminate\Contracts\Container\BindingResolutionException;
use Illuminate\Database\Eloquent\ModelNotFoundException; use Illuminate\Database\Eloquent\ModelNotFoundException;
@@ -15,10 +14,9 @@ use Illuminate\Http\Request;
use Illuminate\Session\TokenMismatchException; use Illuminate\Session\TokenMismatchException;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use Illuminate\Validation\ValidationException as IlluminateValidationException; use Illuminate\Validation\ValidationException as IlluminateValidationException;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\HttpException as SymfonyHttpException; use Symfony\Component\HttpKernel\Exception\HttpException as SymfonyHttpException;
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Throwable;
use Whoops\Handler\HandlerInterface; use Whoops\Handler\HandlerInterface;
/** /**
@@ -42,19 +40,19 @@ class Handler extends ExceptionHandler
/** /**
* Render an exception into an HTTP response. * Render an exception into an HTTP response.
* *
* @param Request $request * @param Request $request
* @param Exception $exception * @param \Throwable $exception
* *
* @return mixed * @return mixed
*/ */
public function render($request, Exception $exception) public function render($request, Throwable $exception)
{ {
if ($request->is('api/*')) { if ($request->is('api/*')) {
return $this->handleApiError($request, $exception); return $this->handleApiError($request, $exception);
} }
if ($exception instanceof AbstractHttpException (new SetActiveTheme())->setTheme($request);
&& $exception->getStatusCode() === 403) { if ($exception instanceof AbstractHttpException && $exception->getStatusCode() === 403) {
return redirect()->guest('login'); return redirect()->guest('login');
} }
@@ -65,11 +63,11 @@ class Handler extends ExceptionHandler
* Handle errors in the API * Handle errors in the API
* *
* @param $request * @param $request
* @param \Exception $exception * @param \Throwable $exception
* *
* @return \Illuminate\Http\JsonResponse|\Illuminate\Http\Response * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\Response
*/ */
private function handleApiError($request, Exception $exception) private function handleApiError($request, Throwable $exception)
{ {
Log::error('API Error', $exception->getTrace()); Log::error('API Error', $exception->getTrace());
@@ -118,38 +116,13 @@ class Handler extends ExceptionHandler
{ {
if ($request->expectsJson() || $request->is('api/*')) { if ($request->expectsJson() || $request->is('api/*')) {
$error = new Unauthenticated(); $error = new Unauthenticated();
return $error->getResponse(); return $error->getResponse();
} }
return redirect()->guest('login'); return redirect()->guest('login');
} }
/**
* Render the given HttpException.
*
* @param AbstractHttpException $e
*
* @return \Illuminate\Http\Response|Response
*/
protected function renderHttpException(HttpExceptionInterface $e)
{
$status = $e->getStatusCode();
view()->replaceNamespace('errors', [
resource_path('views/layouts/'.setting('general.theme', 'default').'/errors'),
resource_path('views/errors'),
__DIR__.'/views',
]);
if (view()->exists("errors::{$status}")) {
return response()->view("errors::{$status}", [
'exception' => $e,
'SKIN_NAME' => setting('general.theme', 'default'),
], $status, $e->getHeaders());
}
return $this->convertExceptionToResponse($e);
}
/** /**
* Ignition error page integration * Ignition error page integration
*/ */
+41
View File
@@ -0,0 +1,41 @@
<?php
namespace App\Exceptions;
class ModuleExistsException extends AbstractHttpException
{
private $module_name;
public function __construct($module_name)
{
$this->module_name = $module_name;
parent::__construct(
409,
'Module '.$module_name.' Already Exists!'
);
}
/**
* Return the RFC 7807 error type (without the URL root)
*/
public function getErrorType(): string
{
return 'module-already-exists';
}
/**
* 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 [];
}
}
@@ -0,0 +1,38 @@
<?php
namespace App\Exceptions;
class ModuleInstallationError extends AbstractHttpException
{
public function __construct()
{
parent::__construct(
500,
'Installation of Module Failed!'
);
}
/**
* Return the RFC 7807 error type (without the URL root)
*/
public function getErrorType(): string
{
return 'module-installation-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 [];
}
}
+38
View File
@@ -0,0 +1,38 @@
<?php
namespace App\Exceptions;
class ModuleInvalidFileType extends AbstractHttpException
{
public function __construct()
{
parent::__construct(
415,
'The Module File Type is Invalid!'
);
}
/**
* Return the RFC 7807 error type (without the URL root)
*/
public function getErrorType(): string
{
return 'module-file-type-invalid';
}
/**
* 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 [];
}
}
+43
View File
@@ -0,0 +1,43 @@
<?php
namespace App\Exceptions;
class PilotIdNotFound extends AbstractHttpException
{
private $pilot_id;
public function __construct($pilot_id)
{
$this->pilot_id = $pilot_id;
parent::__construct(
404,
'Pilot '.$pilot_id.' not found'
);
}
/**
* Return the RFC 7807 error type (without the URL root)
*/
public function getErrorType(): string
{
return 'pilot-id-not-found';
}
/**
* Get the detailed error string
*/
public function getErrorDetails(): string
{
return $this->getMessage();
}
/**
* Return an array with the error details, merged with the RFC7807 response
*/
public function getErrorMetadata(): array
{
return [
'pilot_id' => $this->pilot_id,
];
}
}
+43
View File
@@ -0,0 +1,43 @@
<?php
namespace App\Exceptions;
use Exception;
class Unauthorized extends AbstractHttpException
{
private $exception;
public function __construct(Exception $exception)
{
$this->exception = $exception;
parent::__construct(
403,
$exception->getMessage()
);
}
/**
* Return the RFC 7807 error type (without the URL root)
*/
public function getErrorType(): string
{
return 'unauthorized';
}
/**
* 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 [];
}
}
+46
View File
@@ -0,0 +1,46 @@
<?php
namespace App\Exceptions;
use App\Models\Page;
class UnknownPageType extends AbstractHttpException
{
private $page;
public function __construct(Page $page)
{
$this->page = $page;
parent::__construct(
400,
'Unknown page type "'.$page->type.'"'
);
}
/**
* Return the RFC 7807 error type (without the URL root)
*/
public function getErrorType(): string
{
return 'unknown-page-type';
}
/**
* 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 [
'id' => $this->page->id,
'type' => $this->page->type,
];
}
}
+10 -4
View File
@@ -10,7 +10,10 @@ use Illuminate\View\View;
class PageLinksComposer extends Composer class PageLinksComposer extends Composer
{ {
protected $pageRepo; private static $fields = ['id', 'name', 'slug', 'icon', 'type', 'link', 'new_window'];
/** @var \App\Repositories\PageRepository */
private $pageRepo;
/** /**
* PageLinksComposer constructor. * PageLinksComposer constructor.
@@ -28,13 +31,16 @@ class PageLinksComposer extends Composer
public function compose(View $view) public function compose(View $view)
{ {
try { try {
$w = [
'enabled' => true,
];
// If not logged in, then only get the public pages // If not logged in, then only get the public pages
$w = ['enabled' => true];
if (!Auth::check()) { if (!Auth::check()) {
$w = ['public' => true]; $w['public'] = true;
} }
$pages = $this->pageRepo->findWhere($w, ['id', 'name', 'slug', 'icon']); $pages = $this->pageRepo->findWhere($w, static::$fields);
} catch (Exception $e) { } catch (Exception $e) {
$pages = []; $pages = [];
} }
@@ -12,6 +12,7 @@ use App\Repositories\FareRepository;
use App\Services\ExportService; use App\Services\ExportService;
use App\Services\ImportService; use App\Services\ImportService;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Laracasts\Flash\Flash; use Laracasts\Flash\Flash;
use Prettus\Repository\Criteria\RequestCriteria; use Prettus\Repository\Criteria\RequestCriteria;
@@ -162,6 +163,8 @@ class FareController extends Controller
return redirect(route('admin.fares.index')); return redirect(route('admin.fares.index'));
} }
Log::info('Deleting fare "'.$fare->name.'", id='.$fare->id);
$this->fareRepo->delete($id); $this->fareRepo->delete($id);
Flash::success('Fare deleted successfully.'); Flash::success('Fare deleted successfully.');
@@ -11,6 +11,7 @@ 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
{ {
@@ -36,7 +37,7 @@ class MaintenanceController extends Controller
return view('admin.maintenance.index', [ return view('admin.maintenance.index', [
'cron_path' => $this->cronSvc->getCronExecString(), 'cron_path' => $this->cronSvc->getCronExecString(),
'cron_problem_exists' => $this->cronSvc->cronProblemExists(), 'cron_problem_exists' => $this->cronSvc->cronProblemExists(),
'new_version' => true, //$this->kvpRepo->get('new_version_available', false), 'new_version' => $this->kvpRepo->get('new_version_available', false),
'new_version_tag' => $this->kvpRepo->get('latest_version_tag'), 'new_version_tag' => $this->kvpRepo->get('latest_version_tag'),
]); ]);
} }
@@ -110,6 +111,10 @@ class MaintenanceController extends Controller
{ {
$new_version_tag = $this->kvpRepo->get('latest_version_tag'); $new_version_tag = $this->kvpRepo->get('latest_version_tag');
Log::info('Attempting to update to '.$new_version_tag); Log::info('Attempting to update to '.$new_version_tag);
$module = Module::find('updater');
$module->enable();
return redirect('/update/downloader'); return redirect('/update/downloader');
} }
} }
@@ -0,0 +1,122 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Contracts\Controller;
use App\Services\ModuleService;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\View\Factory;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Redirector;
use Illuminate\View\View;
class ModulesController extends Controller
{
private $moduleSvc;
public function __construct(ModuleService $moduleSvc)
{
$this->moduleSvc = $moduleSvc;
}
/**
* Display a listing of the Module.
*
* @return mixed
*/
public function index()
{
$modules = $this->moduleSvc->getAllModules();
$new_modules = $this->moduleSvc->scan();
return view('admin.modules.index', [
'modules' => $modules,
'new_modules' => $new_modules,
]);
}
/**
* Show the form for creating a new Module.
*
* @return Application|Factory|View
*/
public function create()
{
return view('admin.modules.create');
}
/**
* Store a newly Uploaded Module in the Storage.
*
* @param Request $request
*
* @return Application|RedirectResponse|Redirector
*/
public function store(Request $request)
{
$this->moduleSvc->installModule($request->file('module_file'));
return $this->index();
}
/**
* Show the form for editing the specified Module.
*
* @param $id
*
* @return Application|Factory|View
*/
public function edit($id)
{
$module = $this->moduleSvc->getModule($id);
return view('admin.modules.edit', [
'module' => $module,
]);
}
/**
* Update the specified Module in storage.
*
* @param $id
* @param Request $request
*
* @return Application|RedirectResponse|Redirector
*/
public function update($id, Request $request)
{
$this->moduleSvc->updateModule($id, $request->has('enabled'));
flash()->success('Module Status Changed!');
return redirect(route('admin.modules.index'));
}
/**
* Enabling Module Present in the Modules Folder
*
* @param Request $request
*
* @return Application|RedirectResponse|Redirector
*/
public function enable(Request $request)
{
$this->moduleSvc->addModule($request->input('name'));
return redirect(route('admin.modules.index'));
}
/**
* Verify and Remove the specified Module from storage.
*
* @param mixed $id
* @param Request $request
*
* @return mixed
*/
public function destroy($id, Request $request)
{
$delete = $this->moduleSvc->deleteModule($id, $request->all());
if ($delete == true) {
flash()->success('Module Deleted Successfully!');
return redirect(route('admin.modules.index'));
}
flash()->error('Verification Failed!');
return redirect(route('admin.modules.edit', $id));
}
}
+39 -30
View File
@@ -8,6 +8,7 @@ use App\Http\Requests\UpdateUserRequest;
use App\Models\Rank; use App\Models\Rank;
use App\Models\Role; use App\Models\Role;
use App\Models\User; use App\Models\User;
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;
@@ -20,6 +21,7 @@ use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use Laracasts\Flash\Flash; use Laracasts\Flash\Flash;
use League\ISO3166\ISO3166;
use Prettus\Repository\Exceptions\RepositoryException; use Prettus\Repository\Exceptions\RepositoryException;
class UserController extends Controller class UserController extends Controller
@@ -69,7 +71,7 @@ class UserController extends Controller
return view('admin.users.index', [ return view('admin.users.index', [
'users' => $users, 'users' => $users,
'country' => new \League\ISO3166\ISO3166(), 'country' => new ISO3166(),
]); ]);
} }
@@ -82,13 +84,18 @@ class UserController extends Controller
{ {
$airlines = $this->airlineRepo->selectBoxList(); $airlines = $this->airlineRepo->selectBoxList();
$airports = $this->airportRepo->selectBoxList(false); $airports = $this->airportRepo->selectBoxList(false);
$countries = collect((new ISO3166())->all())
->mapWithKeys(function ($item, $key) {
return [strtolower($item['alpha2']) => $item['name']];
});
return view('admin.users.create', [ return view('admin.users.create', [
'user' => null, 'user' => null,
'pireps' => null, 'pireps' => null,
'airlines' => $airlines, 'airlines' => $airlines,
'timezones' => Timezonelist::toArray(), 'timezones' => Timezonelist::toArray(),
'country' => new \League\ISO3166\ISO3166(), 'country' => new ISO3166(),
'countries' => $countries,
'airports' => $airports, 'airports' => $airports,
'ranks' => Rank::all()->pluck('name', 'id'), 'ranks' => Rank::all()->pluck('name', 'id'),
'roles' => Role::all()->pluck('name', 'id'), 'roles' => Role::all()->pluck('name', 'id'),
@@ -122,31 +129,7 @@ class UserController extends Controller
*/ */
public function show($id) public function show($id)
{ {
$user = $this->userRepo->findWithoutFail($id); return $this->edit($id);
if (empty($user)) {
Flash::error('User not found');
return redirect(route('admin.users.index'));
}
$pireps = $this->pirepRepo
->whereOrder(['user_id' => $id], 'created_at', 'desc')
->paginate();
$airlines = $this->airlineRepo->selectBoxList();
$airports = $this->airportRepo->selectBoxList(false);
return view('admin.users.show', [
'user' => $user,
'pireps' => $pireps,
'airlines' => $airlines,
'timezones' => Timezonelist::toArray(),
'country' => new \League\ISO3166\ISO3166(),
'airports' => $airports,
'ranks' => Rank::all()->pluck('name', 'id'),
'roles' => Role::all()->pluck('name', 'id'),
]);
} }
/** /**
@@ -154,15 +137,18 @@ class UserController extends Controller
* *
* @param int $id * @param int $id
* *
* @throws RepositoryException
*
* @return mixed * @return mixed
*/ */
public function edit($id) public function edit($id)
{ {
$user = $this->userRepo->findWithoutFail($id); $user = $this->userRepo
->with(['awards', 'fields', 'rank'])
->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'));
} }
@@ -170,7 +156,7 @@ class UserController extends Controller
->whereOrder(['user_id' => $id], 'created_at', 'desc') ->whereOrder(['user_id' => $id], 'created_at', 'desc')
->paginate(); ->paginate();
$countries = collect((new \League\ISO3166\ISO3166())->all()) $countries = collect((new ISO3166())->all())
->mapWithKeys(function ($item, $key) { ->mapWithKeys(function ($item, $key) {
return [strtolower($item['alpha2']) => $item['name']]; return [strtolower($item['alpha2']) => $item['name']];
}); });
@@ -181,6 +167,7 @@ class UserController extends Controller
return view('admin.users.edit', [ return view('admin.users.edit', [
'user' => $user, 'user' => $user,
'pireps' => $pireps, 'pireps' => $pireps,
'country' => new ISO3166(),
'countries' => $countries, 'countries' => $countries,
'timezones' => Timezonelist::toArray(), 'timezones' => Timezonelist::toArray(),
'airports' => $airports, 'airports' => $airports,
@@ -279,6 +266,28 @@ class UserController extends Controller
return redirect(route('admin.users.index')); return redirect(route('admin.users.index'));
} }
/**
* Remove the award from a user
*
* @param \Illuminate\Http\Request $request
* @param mixed $id
* @param mixed $award_id
*
* @return \Illuminate\Http\RedirectResponse
*/
public function destroy_user_award($id, $award_id, Request $request)
{
$userAward = UserAward::where(['user_id' => $id, 'award_id' => $award_id]);
if (empty($userAward)) {
Flash::error('The user award could not be found');
return redirect()->back();
}
$userAward->delete();
return redirect()->back();
}
/** /**
* Regenerate the user's API key * Regenerate the user's API key
* *
@@ -0,0 +1,154 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Contracts\Controller;
use App\Repositories\UserFieldRepository;
use Illuminate\Http\Request;
use Laracasts\Flash\Flash;
use Prettus\Repository\Criteria\RequestCriteria;
class UserFieldController extends Controller
{
/** @var \App\Repositories\UserFieldRepository */
private $userFieldRepo;
/**
* @param UserFieldRepository $userFieldRepo
*/
public function __construct(UserFieldRepository $userFieldRepo)
{
$this->userFieldRepo = $userFieldRepo;
}
/**
* Display a listing of the UserField.
*
* @param Request $request
*
* @throws \Prettus\Repository\Exceptions\RepositoryException
*
* @return mixed
*/
public function index(Request $request)
{
$this->userFieldRepo->pushCriteria(new RequestCriteria($request));
$fields = $this->userFieldRepo->all();
return view('admin.userfields.index', ['fields' => $fields]);
}
/**
* Show the form for creating a new UserField.
*/
public function create()
{
return view('admin.userfields.create');
}
/**
* Store a newly created UserField in storage.
*
* @param Request $request
*
* @throws \Prettus\Validator\Exceptions\ValidatorException
*
* @return mixed
*/
public function store(Request $request)
{
$this->userFieldRepo->create($request->all());
Flash::success('Field added successfully.');
return redirect(route('admin.userfields.index'));
}
/**
* Display the specified UserField.
*
* @param int $id
*
* @return mixed
*/
public function show($id)
{
$field = $this->userFieldRepo->findWithoutFail($id);
if (empty($field)) {
Flash::error('Flight field not found');
return redirect(route('admin.userfields.index'));
}
return view('admin.userfields.show', ['field' => $field]);
}
/**
* Show the form for editing the specified UserField.
*
* @param int $id
*
* @return mixed
*/
public function edit($id)
{
$field = $this->userFieldRepo->findWithoutFail($id);
if (empty($field)) {
Flash::error('Field not found');
return redirect(route('admin.userfields.index'));
}
return view('admin.userfields.edit', ['field' => $field]);
}
/**
* Update the specified UserField in storage.
*
* @param $id
* @param Request $request
*
* @throws \Prettus\Validator\Exceptions\ValidatorException
*
* @return mixed
*/
public function update($id, Request $request)
{
$field = $this->userFieldRepo->findWithoutFail($id);
if (empty($field)) {
Flash::error('UserField not found');
return redirect(route('admin.userfields.index'));
}
$this->userFieldRepo->update($request->all(), $id);
Flash::success('Field updated successfully.');
return redirect(route('admin.userfields.index'));
}
/**
* Remove the specified UserField from storage.
*
* @param int $id
*
* @return mixed
*/
public function destroy($id)
{
$field = $this->userFieldRepo->findWithoutFail($id);
if (empty($field)) {
Flash::error('Field not found');
return redirect(route('admin.userfields.index'));
}
if ($this->userFieldRepo->isInUse($id)) {
Flash::error('This field cannot be deleted, it is in use. Deactivate it instead');
return redirect(route('admin.userfields.index'));
}
$this->userFieldRepo->delete($id);
Flash::success('Field deleted successfully.');
return redirect(route('admin.userfields.index'));
}
}
@@ -3,6 +3,7 @@
namespace App\Http\Controllers\Api; namespace App\Http\Controllers\Api;
use App\Contracts\Controller; use App\Contracts\Controller;
use App\Events\AcarsUpdate;
use App\Exceptions\PirepCancelled; use App\Exceptions\PirepCancelled;
use App\Http\Requests\Acars\EventRequest; use App\Http\Requests\Acars\EventRequest;
use App\Http\Requests\Acars\LogRequest; use App\Http\Requests\Acars\LogRequest;
@@ -198,6 +199,9 @@ class AcarsController extends Controller
$pirep->save(); $pirep->save();
// Post a new update for this ACARS position
event(new AcarsUpdate($pirep, $pirep->position));
return $this->message($count.' positions added', $count); return $this->message($count.' positions added', $count);
} }
+28 -10
View File
@@ -9,6 +9,7 @@ use App\Http\Resources\Navdata as NavdataResource;
use App\Models\SimBrief; use App\Models\SimBrief;
use App\Repositories\Criteria\WhereCriteria; use App\Repositories\Criteria\WhereCriteria;
use App\Repositories\FlightRepository; use App\Repositories\FlightRepository;
use App\Services\FareService;
use App\Services\FlightService; use App\Services\FlightService;
use Exception; use Exception;
use Illuminate\Http\Request; use Illuminate\Http\Request;
@@ -18,19 +19,26 @@ use Prettus\Repository\Exceptions\RepositoryException;
class FlightController extends Controller class FlightController extends Controller
{ {
/** @var \App\Services\FareService */
private $fareSvc;
/** @var \App\Repositories\FlightRepository */
private $flightRepo; private $flightRepo;
/** @var \App\Services\FlightService */
private $flightSvc; private $flightSvc;
/** /**
* FlightController constructor. * @param FareService $fareSvc
*
* @param FlightRepository $flightRepo * @param FlightRepository $flightRepo
* @param FlightService $flightSvc * @param FlightService $flightSvc
*/ */
public function __construct( public function __construct(
FareService $fareSvc,
FlightRepository $flightRepo, FlightRepository $flightRepo,
FlightService $flightSvc FlightService $flightSvc
) { ) {
$this->fareSvc = $fareSvc;
$this->flightRepo = $flightRepo; $this->flightRepo = $flightRepo;
$this->flightSvc = $flightSvc; $this->flightSvc = $flightSvc;
} }
@@ -54,9 +62,13 @@ class FlightController extends Controller
*/ */
public function get($id) public function get($id)
{ {
/** @var \App\Models\User $user */
$user = Auth::user(); $user = Auth::user();
/** @var \App\Models\Flight $flight */
$flight = $this->flightRepo->with([ $flight = $this->flightRepo->with([
'airline', 'airline',
'fares',
'subfleets', 'subfleets',
'subfleets.aircraft', 'subfleets.aircraft',
'subfleets.fares', 'subfleets.fares',
@@ -66,7 +78,8 @@ class FlightController extends Controller
}, },
])->find($id); ])->find($id);
$this->flightSvc->filterSubfleets(Auth::user(), $flight); $flight = $this->flightSvc->filterSubfleets($user, $flight);
$flight = $this->fareSvc->getReconciledFaresForFlight($flight);
return new FlightResource($flight); return new FlightResource($flight);
} }
@@ -78,34 +91,38 @@ class FlightController extends Controller
*/ */
public function search(Request $request) public function search(Request $request)
{ {
/** @var \App\Models\User $user */
$user = Auth::user(); $user = Auth::user();
$where = [ $where = [
'active' => true, 'active' => true,
'visible' => true, 'visible' => true,
]; ];
// Allow the option to bypass some of these restrictions for the searches // Allow the option to bypass some of these restrictions for the searches
if (!$request->filled('ignore_restrictions') if (!$request->filled('ignore_restrictions') || $request->get('ignore_restrictions') === '0') {
|| $request->get('ignore_restrictions') === '0'
) {
if (setting('pilots.restrict_to_company')) { if (setting('pilots.restrict_to_company')) {
$where['airline_id'] = Auth::user()->airline_id; $where['airline_id'] = $user->airline_id;
} }
if (setting('pilots.only_flights_from_current')) { if (setting('pilots.only_flights_from_current')) {
$where['dpt_airport_id'] = Auth::user()->curr_airport_id; $where['dpt_airport_id'] = $user->curr_airport_id;
} }
} }
try { try {
$this->flightRepo->resetCriteria(); $this->flightRepo->resetCriteria();
$this->flightRepo->searchCriteria($request); $this->flightRepo->searchCriteria($request);
$this->flightRepo->pushCriteria(new WhereCriteria($request, $where)); $this->flightRepo->pushCriteria(new WhereCriteria($request, $where, [
'airline' => ['active' => true],
]));
$this->flightRepo->pushCriteria(new RequestCriteria($request)); $this->flightRepo->pushCriteria(new RequestCriteria($request));
$flights = $this->flightRepo $flights = $this->flightRepo
->with([ ->with([
'airline', 'airline',
'fares',
'subfleets', 'subfleets',
'subfleets.aircraft', 'subfleets.aircraft',
'subfleets.fares', 'subfleets.fares',
@@ -121,7 +138,8 @@ class FlightController extends Controller
// TODO: Remove any flights here that a user doesn't have permissions to // TODO: Remove any flights here that a user doesn't have permissions to
foreach ($flights as $flight) { foreach ($flights as $flight) {
$this->flightSvc->filterSubfleets(Auth::user(), $flight); $this->flightSvc->filterSubfleets($user, $flight);
$this->fareSvc->getReconciledFaresForFlight($flight);
} }
return FlightResource::collection($flights); return FlightResource::collection($flights);
+4 -6
View File
@@ -61,7 +61,8 @@ class UserController extends Controller
*/ */
protected function getUserId(Request $request) protected function getUserId(Request $request)
{ {
if ($request->get('id') === null) { $id = $request->get('id');
if ($id === null || $id === 'me') {
return Auth::user()->id; return Auth::user()->id;
} }
@@ -89,10 +90,7 @@ class UserController extends Controller
*/ */
public function get($id) public function get($id)
{ {
$user = $this->userRepo $user = $this->userSvc->getUser($id);
->with(['airline', 'bids', 'rank'])
->find($id);
return new UserResource($user); return new UserResource($user);
} }
@@ -108,7 +106,7 @@ class UserController extends Controller
*/ */
public function bids(Request $request) public function bids(Request $request)
{ {
$user = $this->userRepo->find($this->getUserId($request)); $user = $this->userSvc->getUser($this->getUserId($request));
// Add a bid // Add a bid
if ($request->isMethod('PUT') || $request->isMethod('POST')) { if ($request->isMethod('PUT') || $request->isMethod('POST')) {
+70 -9
View File
@@ -3,36 +3,98 @@
namespace App\Http\Controllers\Auth; namespace App\Http\Controllers\Auth;
use App\Contracts\Controller; use App\Contracts\Controller;
use App\Exceptions\PilotIdNotFound;
use App\Models\Enums\UserState; use App\Models\Enums\UserState;
use App\Services\UserService;
use Illuminate\Foundation\Auth\AuthenticatesUsers; use Illuminate\Foundation\Auth\AuthenticatesUsers;
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;
/**
* Class LoginController
*/
class LoginController extends Controller class LoginController extends Controller
{ {
use AuthenticatesUsers; use AuthenticatesUsers;
protected $redirectTo = '/dashboard'; protected $redirectTo = '/dashboard';
/** @var UserService */
private $userSvc;
/** @var string */
private $loginFieldValue;
/** /**
* LoginController constructor. * LoginController constructor.
*
* @param UserService $userSvc
*/ */
public function __construct() public function __construct(UserService $userSvc)
{ {
$this->redirectTo = config('phpvms.login_redirect'); $this->redirectTo = config('phpvms.login_redirect');
$this->middleware('guest', ['except' => 'logout']); $this->middleware('guest', ['except' => 'logout']);
$this->userSvc = $userSvc;
} }
/** /**
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View * Get the needed authorization credentials from the request.
* Overriding the value from the trait
*
* @override
*
* @param \Illuminate\Http\Request $request
*
* @return array
*/ */
public function showLoginForm() protected function credentials(Request $request)
{ {
return view('auth/login'); return [
'email' => $this->loginFieldValue,
'password' => $request->input('password'),
];
}
/**
* Validate the user login request.
*
* @override
*
* @param \Illuminate\Http\Request $request
*
* @return void
*/
protected function validateLogin(Request $request)
{
$id_field = $request->input('email');
$validations = ['required', 'string'];
/*
* Trying to login by email or not?
*
* If not, run a validation rule which attempts to split the user by their VA and ID
* Then inject that user's email into the request
*/
if (strpos($id_field, '@') !== false) {
$validations[] = 'email';
$this->loginFieldValue = $request->input('email');
} else {
$validations[] = function ($attr, $value, $fail) use ($request) {
try {
$user = $this->userSvc->findUserByPilotId($value);
} catch (PilotIdNotFound $ex) {
Log::warning('Error logging in, pilot_id not found, id='.$value);
$fail('Pilot not found');
return;
}
$request->email = $user->email;
$this->loginFieldValue = $user->email;
};
}
$request->validate([
'email' => $validations,
'password' => 'required|string',
]);
} }
/** /**
@@ -47,8 +109,7 @@ class LoginController extends Controller
$user->last_ip = $request->ip(); $user->last_ip = $request->ip();
$user->save(); $user->save();
// TODO: How to handle ON_LEAVE? if ($user->state !== UserState::ACTIVE && $user->state !== UserState::ON_LEAVE) {
if ($user->state !== UserState::ACTIVE) {
Log::info('Trying to login '.$user->ident.', state ' Log::info('Trying to login '.$user->ident.', state '
.UserState::label($user->state)); .UserState::label($user->state));
@@ -3,19 +3,20 @@
namespace App\Http\Controllers\Auth; namespace App\Http\Controllers\Auth;
use App\Contracts\Controller; use App\Contracts\Controller;
use App\Http\Requests\CreateUserRequest;
use App\Models\Enums\UserState; use App\Models\Enums\UserState;
use App\Models\User; use App\Models\User;
use App\Models\UserField;
use App\Models\UserFieldValue;
use App\Repositories\AirlineRepository; use App\Repositories\AirlineRepository;
use App\Repositories\AirportRepository; use App\Repositories\AirportRepository;
use App\Services\UserService; use App\Services\UserService;
use App\Support\Countries; use App\Support\Countries;
use App\Support\Timezonelist; use App\Support\Timezonelist;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Foundation\Auth\RegistersUsers; use Illuminate\Foundation\Auth\RegistersUsers;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Validator;
class RegisterController extends Controller class RegisterController extends Controller
{ {
@@ -61,12 +62,14 @@ 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])->get();
return view('auth.register', [ return view('auth.register', [
'airports' => $airports, 'airports' => $airports,
'airlines' => $airlines, 'airlines' => $airlines,
'countries' => Countries::getSelectList(), 'countries' => Countries::getSelectList(),
'timezones' => Timezonelist::toArray(), 'timezones' => Timezonelist::toArray(),
'userFields' => $userFields,
]); ]);
} }
@@ -81,13 +84,24 @@ class RegisterController extends Controller
{ {
$rules = [ $rules = [
'name' => 'required|max:255', 'name' => 'required|max:255',
'email' => 'required|email|max:255|unique:users, email', 'email' => 'required|email|max:255|unique:users,email',
'airline_id' => 'required', 'airline_id' => 'required',
'home_airport_id' => 'required', 'home_airport_id' => 'required',
'password' => 'required|min:5|confirmed', 'password' => 'required|min:5|confirmed',
'toc_accepted' => 'accepted', 'toc_accepted' => 'accepted',
]; ];
// Dynamically add the required fields
$userFields = UserField::where([
'show_on_registration' => true,
'required' => true,
'active' => true,
])->get();
foreach ($userFields as $field) {
$rules['field_'.$field->slug] = 'required';
}
if (config('captcha.enabled')) { if (config('captcha.enabled')) {
$rules['g-recaptcha-response'] = 'required|captcha'; $rules['g-recaptcha-response'] = 'required|captcha';
} }
@@ -119,6 +133,15 @@ class RegisterController extends Controller
Log::info('User registered: ', $user->toArray()); Log::info('User registered: ', $user->toArray());
$userFields = UserField::all();
foreach ($userFields as $field) {
$field_name = 'field_'.$field->slug;
UserFieldValue::updateOrCreate([
'user_field_id' => $field->id,
'user_id' => $user->id,
], ['value' => $opts[$field_name]]);
}
return $user; return $user;
} }
@@ -131,8 +154,10 @@ class RegisterController extends Controller
* *
* @return mixed * @return mixed
*/ */
public function register(CreateUserRequest $request) public function register(Request $request)
{ {
$this->validator($request->all())->validate();
$user = $this->create($request->all()); $user = $this->create($request->all());
if ($user->state === UserState::PENDING) { if ($user->state === UserState::PENDING) {
return view('auth.pending'); return view('auth.pending');
@@ -79,20 +79,26 @@ class FlightController extends Controller
'visible' => true, 'visible' => true,
]; ];
/** @var \App\Models\User $user */
$user = Auth::user();
if (setting('pilots.restrict_to_company')) { if (setting('pilots.restrict_to_company')) {
$where['airline_id'] = Auth::user()->airline_id; $where['airline_id'] = $user->airline_id;
} }
// default restrictions on the flights shown. Handle search differently // default restrictions on the flights shown. Handle search differently
if (setting('pilots.only_flights_from_current')) { if (setting('pilots.only_flights_from_current')) {
$where['dpt_airport_id'] = Auth::user()->curr_airport_id; $where['dpt_airport_id'] = $user->curr_airport_id;
} }
$this->flightRepo->resetCriteria(); $this->flightRepo->resetCriteria();
try { try {
$this->flightRepo->searchCriteria($request); $this->flightRepo->searchCriteria($request);
$this->flightRepo->pushCriteria(new WhereCriteria($request, $where)); $this->flightRepo->pushCriteria(new WhereCriteria($request, $where, [
'airline' => ['active' => true],
]));
$this->flightRepo->pushCriteria(new RequestCriteria($request)); $this->flightRepo->pushCriteria(new RequestCriteria($request));
} catch (RepositoryException $e) { } catch (RepositoryException $e) {
Log::emergency($e); Log::emergency($e);
@@ -4,8 +4,10 @@ namespace App\Http\Controllers\Frontend;
use App\Contracts\Controller; use App\Contracts\Controller;
use App\Exceptions\PageNotFound; use App\Exceptions\PageNotFound;
use App\Exceptions\Unauthorized;
use App\Repositories\PageRepository; use App\Repositories\PageRepository;
use Exception; use Exception;
use Illuminate\Support\Facades\Auth;
class PageController extends Controller class PageController extends Controller
{ {
@@ -28,11 +30,16 @@ class PageController extends Controller
*/ */
public function show($slug) public function show($slug)
{ {
/** @var \App\Models\Page $page */
$page = $this->pageRepo->findWhere(['slug' => $slug])->first(); $page = $this->pageRepo->findWhere(['slug' => $slug])->first();
if (!$page) { if (!$page) {
throw new PageNotFound(new Exception('Page not found')); throw new PageNotFound(new Exception('Page not found'));
} }
if (!$page->public && !Auth::check()) {
throw new Unauthorized(new Exception('You must be logged in to view this page'));
}
return view('pages.index', ['page' => $page]); return view('pages.index', ['page' => $page]);
} }
} }
@@ -10,6 +10,7 @@ use App\Models\Enums\PirepState;
use App\Models\Enums\PirepStatus; use App\Models\Enums\PirepStatus;
use App\Models\Pirep; use App\Models\Pirep;
use App\Models\SimBrief; use App\Models\SimBrief;
use App\Models\User;
use App\Repositories\AircraftRepository; use App\Repositories\AircraftRepository;
use App\Repositories\AirlineRepository; use App\Repositories\AirlineRepository;
use App\Repositories\AirportRepository; use App\Repositories\AirportRepository;
@@ -180,8 +181,9 @@ class PirepController extends Controller
$where = [['user_id', $user->id]]; $where = [['user_id', $user->id]];
$where[] = ['state', '<>', PirepState::CANCELLED]; $where[] = ['state', '<>', PirepState::CANCELLED];
$with = ['airline', 'aircraft', 'dpt_airport', 'arr_airport', 'fares', 'comments'];
$this->pirepRepo->with(['airline', 'aircraft', 'dpt_airport', 'arr_airport']) $this->pirepRepo->with($with)
->pushCriteria(new WhereCriteria($request, $where)); ->pushCriteria(new WhereCriteria($request, $where));
$pireps = $this->pirepRepo->orderBy('created_at', 'desc')->paginate(); $pireps = $this->pirepRepo->orderBy('created_at', 'desc')->paginate();
@@ -280,9 +282,11 @@ class PirepController extends Controller
*/ */
public function store(CreatePirepRequest $request) public function store(CreatePirepRequest $request)
{ {
// Create the main PIREP /** @var User $user */
$user = Auth::user();
$pirep = new Pirep($request->post()); $pirep = new Pirep($request->post());
$pirep->user_id = Auth::user()->id; $pirep->user_id = $user->id;
$attrs = $request->all(); $attrs = $request->all();
$attrs['submit'] = strtolower($attrs['submit']); $attrs['submit'] = strtolower($attrs['submit']);
@@ -290,8 +294,13 @@ class PirepController extends Controller
if ($attrs['submit'] === 'submit') { if ($attrs['submit'] === 'submit') {
// Are they allowed at this airport? // Are they allowed at this airport?
if (setting('pilots.only_flights_from_current') if (setting('pilots.only_flights_from_current')
&& Auth::user()->curr_airport_id !== $pirep->dpt_airport_id) { && $user->curr_airport_id !== $pirep->dpt_airport_id) {
Log::info('Pilot '.Auth::user()->id.' not at departure airport, erroring out'); Log::info(
'Pilot '.$user->id
.' not at departure airport (curr='.$user->curr_airport_id
.', dpt='.$pirep->dpt_airport_id.')'
);
return $this->flashError( return $this->flashError(
'You are currently not at the departure airport!', 'You are currently not at the departure airport!',
'frontend.pireps.create' 'frontend.pireps.create'
@@ -300,8 +309,8 @@ class PirepController extends Controller
// Can they fly this aircraft? // Can they fly this aircraft?
if (setting('pireps.restrict_aircraft_to_rank', false) if (setting('pireps.restrict_aircraft_to_rank', false)
&& !$this->userSvc->aircraftAllowed(Auth::user(), $pirep->aircraft_id)) { && !$this->userSvc->aircraftAllowed($user, $pirep->aircraft_id)) {
Log::info('Pilot '.Auth::user()->id.' not allowed to fly aircraft'); Log::info('Pilot '.$user->id.' not allowed to fly aircraft');
return $this->flashError( return $this->flashError(
'You are not allowed to fly this aircraft!', 'You are not allowed to fly this aircraft!',
'frontend.pireps.create' 'frontend.pireps.create'
@@ -310,9 +319,20 @@ class PirepController extends Controller
// is the aircraft in the right place? // is the aircraft in the right place?
/* @noinspection NotOptimalIfConditionsInspection */ /* @noinspection NotOptimalIfConditionsInspection */
// Get the aircraft
$aircraft = $this->aircraftRepo->findWithoutFail($pirep->aircraft_id);
if ($aircraft === null) {
Log::error('Aircraft for PIREP not found, id='.$pirep->aircraft_id);
return $this->flashError(
'The aircraft for the PIREP hasn\'t been found',
'frontend.pireps.create'
);
}
if (setting('pireps.only_aircraft_at_dpt_airport') if (setting('pireps.only_aircraft_at_dpt_airport')
&& $pirep->aircraft_id !== $pirep->dpt_airport_id) { && $aircraft->airport_id !== $pirep->dpt_airport_id
Log::info('Aircraft '.$pirep->aircraft_id.' not at departure airport '.$pirep->dpt_airport_id.', erroring out'); ) {
Log::info('Aircraft '.$pirep->aircraft_id.' not at departure airport (curr='.$pirep->aircraft->airport_id.', apt='.$pirep->dpt_airport_id.')');
return $this->flashError( return $this->flashError(
'This aircraft is not positioned at the departure airport!', 'This aircraft is not positioned at the departure airport!',
'frontend.pireps.create' 'frontend.pireps.create'
@@ -4,6 +4,8 @@ namespace App\Http\Controllers\Frontend;
use App\Contracts\Controller; use App\Contracts\Controller;
use App\Models\User; use App\Models\User;
use App\Models\UserField;
use App\Models\UserFieldValue;
use App\Repositories\AirlineRepository; use App\Repositories\AirlineRepository;
use App\Repositories\AirportRepository; use App\Repositories\AirportRepository;
use App\Repositories\UserRepository; use App\Repositories\UserRepository;
@@ -59,21 +61,14 @@ class ProfileController extends Controller
} }
/** /**
* Redirect to show() since only a single page gets shown and the template controls
* the other items that are/aren't shown
*
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/ */
public function index() public function index()
{ {
if (setting('pilots.home_hubs_only')) { return $this->show(Auth::user()->id);
$airports = $this->airportRepo->findWhere(['hub' => true]);
} else {
$airports = $this->airportRepo->all();
}
return view('profile.index', [
'acars' => $this->acarsEnabled(),
'user' => Auth::user(),
'airports' => $airports,
]);
} }
/** /**
@@ -83,18 +78,23 @@ class ProfileController extends Controller
*/ */
public function show($id) public function show($id)
{ {
$user = User::where('id', $id)->first(); /** @var \App\Models\User $user */
$user = User::with(['awards', 'fields', 'fields.field'])
->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(); $airports = $this->airportRepo->all();
$userFields = $this->userRepo->getUserFields($user, true);
return view('profile.index', [ return view('profile.index', [
'user' => $user, 'user' => $user,
'airports' => $airports, 'userFields' => $userFields,
'airports' => $airports,
]); ]);
} }
@@ -109,22 +109,27 @@ class ProfileController extends Controller
*/ */
public function edit(Request $request) public function edit(Request $request)
{ {
$user = User::where('id', Auth::user()->id)->first(); /** @var \App\Models\User $user */
$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!');
return redirect(route('frontend.dashboard.index')); return redirect(route('frontend.dashboard.index'));
} }
$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, false);
return view('profile.edit', [ return view('profile.edit', [
'user' => $user, 'user' => $user,
'airlines' => $airlines, 'airlines' => $airlines,
'airports' => $airports, 'airports' => $airports,
'countries' => Countries::getSelectList(), 'countries' => Countries::getSelectList(),
'timezones' => Timezonelist::toArray(), 'timezones' => Timezonelist::toArray(),
'userFields' => $userFields,
]); ]);
} }
@@ -140,13 +145,20 @@ class ProfileController extends Controller
$id = Auth::user()->id; $id = Auth::user()->id;
$user = $this->userRepo->findWithoutFail($id); $user = $this->userRepo->findWithoutFail($id);
$validator = Validator::make($request->toArray(), [ $rules = [
'name' => 'required', 'name' => 'required',
'email' => 'required|unique:users,email,'.$id, 'email' => 'required|unique:users,email,'.$id,
'airline_id' => 'required', 'airline_id' => 'required',
'password' => 'confirmed', 'password' => 'confirmed',
'avatar' => 'nullable|mimes:jpeg,png,jpg', 'avatar' => 'nullable|mimes:jpeg,png,jpg',
]); ];
$userFields = UserField::where(['show_on_registration' => true, 'required' => true])->get();
foreach ($userFields as $field) {
$rules['field_'.$field->slug] = 'required';
}
$validator = Validator::make($request->toArray(), $rules);
if ($validator->fails()) { if ($validator->fails()) {
Log::info('validator failed for user '.$user->ident); Log::info('validator failed for user '.$user->ident);
@@ -167,6 +179,7 @@ class ProfileController extends Controller
if (isset($req_data['avatar']) !== null) { if (isset($req_data['avatar']) !== null) {
Storage::delete($user->avatar); Storage::delete($user->avatar);
} }
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();
@@ -190,6 +203,16 @@ class ProfileController extends Controller
$this->userRepo->update($req_data, $id); $this->userRepo->update($req_data, $id);
// Save all of the user fields
$userFields = UserField::all();
foreach ($userFields as $field) {
$field_name = 'field_'.$field->slug;
UserFieldValue::updateOrCreate([
'user_field_id' => $field->id,
'user_id' => $id,
], ['value' => $request->get($field_name)]);
}
Flash::success('Profile updated successfully!'); Flash::success('Profile updated successfully!');
return redirect(route('frontend.profile.index')); return redirect(route('frontend.profile.index'));
@@ -1,14 +1,14 @@
<?php <?php
namespace Modules\Importer\Http\Controllers; namespace App\Http\Controllers\System;
use App\Contracts\Controller; use App\Contracts\Controller;
use App\Services\ImporterService;
use App\Services\Installer\DatabaseService; use App\Services\Installer\DatabaseService;
use App\Services\Installer\InstallerService;
use App\Support\Utils; use App\Support\Utils;
use Exception;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use Modules\Importer\Services\ImporterService;
class ImporterController extends Controller class ImporterController extends Controller
{ {
@@ -27,13 +27,11 @@ class ImporterController extends Controller
* Show the main page for the importer; show form for the admin email * Show the main page for the importer; show form for the admin email
* and the credentials for the other database * and the credentials for the other database
* *
* @param \Illuminate\Http\Request $request
*
* @return mixed * @return mixed
*/ */
public function index(Request $request) public function index()
{ {
return view('importer::step1-configure'); return view('system.importer.step1-configure');
} }
protected function testDb(Request $request) protected function testDb(Request $request)
@@ -51,7 +49,7 @@ class ImporterController extends Controller
/** /**
* Check the database connection * Check the database connection
* *
* @param \Illuminate\Http\Request $request * @param Request $request
* *
* @return mixed * @return mixed
*/ */
@@ -62,12 +60,12 @@ class ImporterController extends Controller
try { try {
$this->testDb($request); $this->testDb($request);
} catch (\Exception $e) { } catch (Exception $e) {
$status = 'danger'; $status = 'danger';
$message = 'Failed! '.$e->getMessage(); $message = 'Failed! '.$e->getMessage();
} }
return view('importer::dbtest', [ return view('system.importer.dbtest', [
'status' => $status, 'status' => $status,
'message' => $message, 'message' => $message,
]); ]);
@@ -76,7 +74,7 @@ class ImporterController extends Controller
/** /**
* The post from the above * The post from the above
* *
* @param \Illuminate\Http\Request $request * @param Request $request
* *
* @return mixed * @return mixed
*/ */
@@ -90,17 +88,17 @@ class ImporterController extends Controller
// Generate the import manifest // Generate the import manifest
$manifest = $this->importerSvc->generateImportManifest(); $manifest = $this->importerSvc->generateImportManifest();
} catch (\Exception $e) { } catch (Exception $e) {
Log::error($e->getMessage()); Log::error($e->getMessage());
// Send it to run, step1 // Send it to run, step1
return view('importer::error', [ return view('system.importer.error', [
'error' => $e->getMessage(), 'error' => $e->getMessage(),
]); ]);
} }
// Send it to run, step1 // Send it to run, step1
return view('importer::step2-processing', [ return view('system.importer.step2-processing', [
'manifest' => $manifest, 'manifest' => $manifest,
]); ]);
} }
@@ -111,9 +109,9 @@ class ImporterController extends Controller
* stage=STAGE NAME * stage=STAGE NAME
* start=record_start * start=record_start
* *
* @param \Illuminate\Http\Request $request * @param Request $request
* *
* @throws \Exception * @throws Exception
* *
* @return mixed * @return mixed
*/ */
@@ -136,9 +134,6 @@ class ImporterController extends Controller
*/ */
public function complete() public function complete()
{ {
$installerSvc = app(InstallerService::class);
$installerSvc->disableInstallerModules();
return redirect('/'); return redirect('/');
} }
} }
@@ -1,25 +1,32 @@
<?php <?php
namespace Modules\Installer\Http\Controllers; namespace App\Http\Controllers\System;
use App\Contracts\Controller; use App\Contracts\Controller;
use App\Services\AirlineService; use App\Services\AirlineService;
use App\Services\AnalyticsService; use App\Services\AnalyticsService;
use App\Services\Installer\ConfigService;
use App\Services\Installer\DatabaseService; use App\Services\Installer\DatabaseService;
use App\Services\Installer\InstallerService;
use App\Services\Installer\MigrationService; use App\Services\Installer\MigrationService;
use App\Services\Installer\RequirementsService;
use App\Services\Installer\SeederService; use App\Services\Installer\SeederService;
use App\Services\UserService; use App\Services\UserService;
use App\Support\Countries; use App\Support\Countries;
use App\Support\Utils; use App\Support\Utils;
use Exception;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\View\Factory;
use Illuminate\Database\QueryException; use Illuminate\Database\QueryException;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Routing\Redirector;
use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Validator; use Illuminate\Support\Facades\Validator;
use Illuminate\View\View;
use function in_array;
use Laracasts\Flash\Flash; use Laracasts\Flash\Flash;
use Modules\Installer\Services\ConfigService; use RuntimeException;
use Modules\Installer\Services\RequirementsService;
class InstallerController extends Controller class InstallerController extends Controller
{ {
@@ -72,10 +79,10 @@ class InstallerController extends Controller
public function index() public function index()
{ {
if (config('app.key') !== 'base64:zdgcDqu9PM8uGWCtMxd74ZqdGJIrnw812oRMmwDF6KY=') { if (config('app.key') !== 'base64:zdgcDqu9PM8uGWCtMxd74ZqdGJIrnw812oRMmwDF6KY=') {
return view('installer::errors/already-installed'); return view('system.installer.errors.already-installed');
} }
return view('installer::install/index-start'); return view('system.installer.install.index-start');
} }
protected function testDb(Request $request) protected function testDb(Request $request)
@@ -92,6 +99,10 @@ class InstallerController extends Controller
/** /**
* Check the database connection * Check the database connection
*
* @param Request $request
*
* @return Application|Factory|View
*/ */
public function dbtest(Request $request) public function dbtest(Request $request)
{ {
@@ -100,12 +111,12 @@ class InstallerController extends Controller
try { try {
$this->testDb($request); $this->testDb($request);
} catch (\Exception $e) { } catch (Exception $e) {
$status = 'danger'; $status = 'danger';
$message = 'Failed! '.$e->getMessage(); $message = 'Failed! '.$e->getMessage();
} }
return view('installer::install/dbtest', [ return view('system.installer.install.dbtest', [
'status' => $status, 'status' => $status,
'message' => $message, 'message' => $message,
]); ]);
@@ -132,11 +143,9 @@ class InstallerController extends Controller
/** /**
* Step 1. Check the modules and permissions * Step 1. Check the modules and permissions
* *
* @param Request $request * @return Factory|View
*
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/ */
public function step1(Request $request) public function step1()
{ {
$php_version = $this->reqSvc->checkPHPVersion(); $php_version = $this->reqSvc->checkPHPVersion();
$extensions = $this->reqSvc->checkExtensions(); $extensions = $this->reqSvc->checkExtensions();
@@ -150,9 +159,9 @@ class InstallerController extends Controller
]; ];
// Make sure there are no false values // Make sure there are no false values
$passed = !\in_array(false, $statuses, true); $passed = !in_array(false, $statuses, true);
return view('installer::install/steps/step1-requirements', [ return view('system.installer.install.steps.step1-requirements', [
'php' => $php_version, 'php' => $php_version,
'extensions' => $extensions, 'extensions' => $extensions,
'directories' => $directories, 'directories' => $directories,
@@ -163,14 +172,12 @@ class InstallerController extends Controller
/** /**
* Step 2. Database Setup * Step 2. Database Setup
* *
* @param Request $request * @return Factory|View
*
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/ */
public function step2(Request $request) public function step2()
{ {
$db_types = ['mysql' => 'mysql', 'sqlite' => 'sqlite']; $db_types = ['mysql' => 'mysql', 'sqlite' => 'sqlite'];
return view('installer::install/steps/step2-db', [ return view('system.installer.install.steps.step2-db', [
'db_types' => $db_types, 'db_types' => $db_types,
]); ]);
} }
@@ -180,7 +187,7 @@ class InstallerController extends Controller
* *
* @param Request $request * @param Request $request
* *
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector * @return RedirectResponse|Redirector
*/ */
public function envsetup(Request $request) public function envsetup(Request $request)
{ {
@@ -192,7 +199,7 @@ class InstallerController extends Controller
// Before writing out the env file, test the DB credentials // Before writing out the env file, test the DB credentials
try { try {
$this->testDb($request); $this->testDb($request);
} catch (\Exception $e) { } catch (Exception $e) {
Log::error('Testing db before writing configs failed'); Log::error('Testing db before writing configs failed');
Log::error($e->getMessage()); Log::error($e->getMessage());
@@ -220,7 +227,7 @@ class InstallerController extends Controller
*/ */
try { try {
$this->envSvc->createConfigFiles($attrs); $this->envSvc->createConfigFiles($attrs);
} catch (\Exception $e) { } catch (Exception $e) {
Log::error('Config files failed to write'); Log::error('Config files failed to write');
Log::error($e->getMessage()); Log::error($e->getMessage());
@@ -236,11 +243,9 @@ class InstallerController extends Controller
/** /**
* Step 2b. Setup the database * Step 2b. Setup the database
* *
* @param Request $request
*
* @return mixed * @return mixed
*/ */
public function dbsetup(Request $request) public function dbsetup()
{ {
$console_out = ''; $console_out = '';
@@ -250,7 +255,7 @@ class InstallerController extends Controller
$this->seederSvc->syncAllSeeds(); $this->seederSvc->syncAllSeeds();
} catch (QueryException $e) { } catch (QueryException $e) {
Log::error('Error on db setup: '.$e->getMessage()); Log::error('Error on db setup: '.$e->getMessage());
dd($e); //dd($e);
$this->envSvc->removeConfigFiles(); $this->envSvc->removeConfigFiles();
Flash::error($e->getMessage()); Flash::error($e->getMessage());
return redirect(route('installer.step2'))->withInput(); return redirect(route('installer.step2'))->withInput();
@@ -258,7 +263,7 @@ class InstallerController extends Controller
$console_out = trim($console_out); $console_out = trim($console_out);
return view('installer::install/steps/step2a-db_output', [ return view('system.installer.install.steps.step2a-db_output', [
'console_output' => $console_out, 'console_output' => $console_out,
]); ]);
} }
@@ -266,9 +271,9 @@ class InstallerController extends Controller
/** /**
* Step 3. Setup the admin user and initial settings * Step 3. Setup the admin user and initial settings
*/ */
public function step3(Request $request) public function step3()
{ {
return view('installer::install/steps/step3-user', [ return view('system.installer.install.steps.step3-user', [
'countries' => Countries::getSelectList(), 'countries' => Countries::getSelectList(),
]); ]);
} }
@@ -278,9 +283,8 @@ class InstallerController extends Controller
* *
* @param Request $request * @param Request $request
* *
* @throws \RuntimeException * @throws RuntimeException
* @throws \Prettus\Validator\Exceptions\ValidatorException * @throws Exception
* @throws \Exception
* *
* @return mixed * @return mixed
*/ */
@@ -337,21 +341,16 @@ class InstallerController extends Controller
// Try sending telemetry info // Try sending telemetry info
$this->analyticsSvc->sendInstall(); $this->analyticsSvc->sendInstall();
return view('installer::install/steps/step3a-completed', []); return view('system.installer.install.steps.step3a-completed', []);
} }
/** /**
* Final step * Final step
* *
* @param Request $request * @return RedirectResponse|Redirector
*
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
*/ */
public function complete(Request $request) public function complete()
{ {
$installerSvc = app(InstallerService::class);
$installerSvc->disableInstallerModules();
return redirect('/login'); return redirect('/login');
} }
} }
@@ -1,19 +1,23 @@
<?php <?php
namespace Modules\Updater\Http\Controllers; namespace App\Http\Controllers\System;
use App\Contracts\Controller; use App\Contracts\Controller;
use App\Repositories\KvpRepository; 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 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 $kvpRepo;
private $migrationSvc; private $migrationSvc;
@@ -21,19 +25,22 @@ class UpdateController extends Controller
private $updateManager; 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 KvpRepository $kvpRepo
* @param UpdaterManager $updateManager * @param UpdaterManager $updateManager
*/ */
public function __construct( public function __construct(
AnalyticsService $analyticsSvc,
InstallerService $installerSvc, InstallerService $installerSvc,
KvpRepository $kvpRepo, KvpRepository $kvpRepo,
MigrationService $migrationSvc, MigrationService $migrationSvc,
SeederService $seederSvc, SeederService $seederSvc,
UpdaterManager $updateManager UpdaterManager $updateManager
) { ) {
$this->analyticsSvc = $analyticsSvc;
$this->migrationSvc = $migrationSvc; $this->migrationSvc = $migrationSvc;
$this->seederSvc = $seederSvc; $this->seederSvc = $seederSvc;
$this->installerSvc = $installerSvc; $this->installerSvc = $installerSvc;
@@ -46,18 +53,16 @@ class UpdateController extends Controller
*/ */
public function index() public function index()
{ {
return view('updater::index-start'); return view('system.updater.index-start');
} }
/** /**
* Step 1. Check if there's an update available. Check if there * Step 1. Check if there's an update available. Check if there
* are any unrun migrations * are any unrun migrations
* *
* @param Request $request
*
* @return mixed * @return mixed
*/ */
public function step1(Request $request) public function step1()
{ {
$this->installerSvc->clearCaches(); $this->installerSvc->clearCaches();
@@ -65,7 +70,7 @@ class UpdateController extends Controller
Log::info('Upgrade is pending'); Log::info('Upgrade is pending');
} }
return view('updater::steps/step1-update-available'); return view('system.updater.steps.step1-update-available');
} }
/** /**
@@ -82,13 +87,13 @@ class UpdateController extends Controller
$migrations = $this->migrationSvc->migrationsAvailable(); $migrations = $this->migrationSvc->migrationsAvailable();
if (count($migrations) === 0) { if (count($migrations) === 0) {
$this->seederSvc->syncAllSeeds(); $this->seederSvc->syncAllSeeds();
return view('updater::steps/step3-update-complete'); return view('system.updater.steps.step3-update-complete');
} }
$output = $this->migrationSvc->runAllMigrations(); $output = $this->migrationSvc->runAllMigrations();
$this->seederSvc->syncAllSeeds(); $this->seederSvc->syncAllSeeds();
return view('updater::steps/step2-migrations-done', [ return view('system.updater.steps.step2-migrations-done', [
'console_output' => $output, 'console_output' => $output,
]); ]);
} }
@@ -96,27 +101,23 @@ class UpdateController extends Controller
/** /**
* Final step * Final step
* *
* @param Request $request
*
* @return mixed * @return mixed
*/ */
public function complete(Request $request) public function complete()
{ {
return redirect('/login'); return redirect('/admin');
} }
/** /**
* Show the update page with the latest version * Show the update page with the latest version
* *
* @param \Illuminate\Http\Request $request * @return Factory|View
*
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/ */
public function updater(Request $request) public function updater()
{ {
$version = $this->kvpRepo->get('latest_version_tag'); $version = $this->kvpRepo->get('latest_version_tag');
return view('updater::downloader/downloader', [ return view('system.updater.downloader/downloader', [
'version' => $version, 'version' => $version,
]); ]);
} }
@@ -124,14 +125,18 @@ class UpdateController extends Controller
/** /**
* Download the actual update and then forward the user to the updater page * Download the actual update and then forward the user to the updater page
* *
* @param \Illuminate\Http\Request $request
*
* @return mixed * @return mixed
*/ */
public function update_download(Request $request) public function update_download()
{ {
$version = $this->kvpRepo->get('latest_version_tag'); $version = $this->kvpRepo->get('latest_version_tag');
$this->updateManager->source('github')->update($version); 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'); Log::info('Update completed to '.$version.', redirecting');
return redirect('/update'); return redirect('/update');
+1
View File
@@ -45,6 +45,7 @@ class Kernel extends HttpKernel
ShareErrorsFromSession::class, ShareErrorsFromSession::class,
// VerifyCsrfToken::class, // VerifyCsrfToken::class,
SubstituteBindings::class, SubstituteBindings::class,
SetActiveTheme::class,
], ],
]; ];
+36 -2
View File
@@ -13,8 +13,44 @@ use Illuminate\Support\Facades\Log;
*/ */
class SetActiveTheme implements Middleware class SetActiveTheme implements Middleware
{ {
private static $skip = [
'admin',
'admin/*',
'api',
'api/*',
'importer',
'importer/*',
'install',
'install/*',
'update',
'update/*',
];
/**
* Handle the request
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
*
* @return mixed
*/
public function handle(Request $request, Closure $next) public function handle(Request $request, Closure $next)
{ {
$this->setTheme($request);
return $next($request);
}
/**
* Set the theme for the current middleware
*
* @param \Illuminate\Http\Request $request
*/
public function setTheme(Request $request)
{
if ($request->is(self::$skip)) {
return;
}
try { try {
$theme = setting('general.theme'); $theme = setting('general.theme');
} catch (\Exception $e) { } catch (\Exception $e) {
@@ -25,7 +61,5 @@ class SetActiveTheme implements Middleware
if (!empty($theme)) { if (!empty($theme)) {
Theme::set($theme); Theme::set($theme);
} }
return $next($request);
} }
} }
+1 -1
View File
@@ -11,7 +11,7 @@ class PrefileRequest extends FormRequest
return [ return [
'airline_id' => 'required|exists:airlines,id', 'airline_id' => 'required|exists:airlines,id',
'aircraft_id' => 'required|exists:aircraft,id', 'aircraft_id' => 'required|exists:aircraft,id',
'flight_id' => 'sometimes|exists:flights,id', 'flight_id' => 'sometimes|nullable|exists:flights,id',
'flight_number' => 'required', 'flight_number' => 'required',
'dpt_airport_id' => 'required', 'dpt_airport_id' => 'required',
'arr_airport_id' => 'required', 'arr_airport_id' => 'required',
+1 -1
View File
@@ -19,7 +19,7 @@ class UpdatePageRequest extends FormRequest
'required', 'required',
Rule::unique('pages')->ignore($this->id, 'id'), Rule::unique('pages')->ignore($this->id, 'id'),
], ],
'body' => 'required', 'body' => 'nullable',
]; ];
} }
} }
+2 -2
View File
@@ -15,9 +15,9 @@ class Fare extends Resource
'id' => $this->id, 'id' => $this->id,
'code' => $this->code, 'code' => $this->code,
'name' => $this->name, 'name' => $this->name,
'price' => $this->price,
'cost' => $this->cost,
'capacity' => $this->capacity, 'capacity' => $this->capacity,
'cost' => $this->cost,
'price' => $this->price,
'type' => $this->type, 'type' => $this->type,
'notes' => $this->notes, 'notes' => $this->notes,
'active' => $this->active, 'active' => $this->active,
+4 -4
View File
@@ -18,17 +18,17 @@ class Flight extends Resource
private function setFields() private function setFields()
{ {
/** @var \Illuminate\Support\Collection $field_values */ /** @var \Illuminate\Support\Collection $field_values */
$return_values = new stdClass();
$field_values = $this->field_values; $field_values = $this->field_values;
if (empty($field_values) || $field_values->count() === 0) { if (empty($field_values) || $field_values->count() === 0) {
return new stdClass(); return $return_values;
} }
$fields = [];
foreach ($field_values as $field) { foreach ($field_values as $field) {
$fields[$field->name] = $field->value; $return_values->{$field->name} = $field->value;
} }
return $fields; return $return_values;
} }
/** /**
+1 -1
View File
@@ -2,7 +2,7 @@
namespace App\Http\Resources; namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\Resource; use App\Contracts\Resource;
/** /**
* @mixin \App\Models\SimBrief * @mixin \App\Models\SimBrief
+1
View File
@@ -31,6 +31,7 @@ class User extends Resource
$res['airline'] = Airline::make($this->whenLoaded('airline')); $res['airline'] = Airline::make($this->whenLoaded('airline'));
$res['bids'] = UserBid::collection($this->whenLoaded('bids')); $res['bids'] = UserBid::collection($this->whenLoaded('bids'));
$res['rank'] = Rank::make($this->whenLoaded('rank')); $res['rank'] = Rank::make($this->whenLoaded('rank'));
$res['subfleets'] = Subfleet::make($this->whenLoaded('subfleets'));
return $res; return $res;
} }
+71
View File
@@ -0,0 +1,71 @@
<?php
namespace App\Listeners;
use App\Contracts\Listener;
use App\Events\PirepAccepted;
use App\Events\UserStateChanged;
use App\Events\UserStatsChanged;
use App\Models\Award;
/**
* 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 AwardHandler extends Listener
{
/** The events and the callback */
public static $callbacks = [
PirepAccepted::class => 'onPirepAccept',
UserStatsChanged::class => 'onUserStatsChanged',
UserStateChanged::class => 'onUserStateChanged',
];
/**
* Called when a PIREP is accepted
*
* @param \App\Events\PirepAccepted $event
*/
public function onPirepAccept(PirepAccepted $event)
{
$this->checkForAwards($event->pirep->user);
}
/**
* When the user's state has changed
*
* @param \App\Events\UserStateChanged $event
*/
public function onUserStateChanged(UserStateChanged $event): void
{
$this->checkForAwards($event->user);
}
/**
* Called when any of the user's states have changed
*
* @param UserStatsChanged $event
*/
public function onUserStatsChanged(UserStatsChanged $event): void
{
$this->checkForAwards($event->user);
}
/**
* Check for any awards to be run and test them against the user
*
* @param \App\Models\User $user
*/
public function checkForAwards($user)
{
$awards = Award::all();
foreach ($awards as $award) {
$klass = $award->getReference($award, $user);
if ($klass) {
$klass->handle();
}
}
}
}
-32
View File
@@ -1,32 +0,0 @@
<?php
namespace App\Listeners;
use App\Contracts\Listener;
use App\Events\UserStatsChanged;
use App\Models\Award;
/**
* 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 AwardListener extends Listener
{
/**
* Call all of the awards
*
* @param UserStatsChanged $event
*/
public function handle(UserStatsChanged $event): void
{
$awards = Award::all();
foreach ($awards as $award) {
$klass = $award->getReference($award, $event->user);
if ($klass) {
$klass->handle();
}
}
}
}
+6
View File
@@ -16,6 +16,8 @@ use Carbon\Carbon;
* @property string icao * @property string icao
* @property string registration * @property string registration
* @property int flight_time * @property int flight_time
* @property float mtow
* @property float zfw
* @property string hex_code * @property string hex_code
* @property Airport airport * @property Airport airport
* @property Subfleet subfleet * @property Subfleet subfleet
@@ -39,6 +41,7 @@ class Aircraft extends Model
'registration', 'registration',
'hex_code', 'hex_code',
'flight_time', 'flight_time',
'mtow',
'zfw', 'zfw',
'status', 'status',
'state', 'state',
@@ -49,6 +52,7 @@ class Aircraft extends Model
*/ */
protected $casts = [ protected $casts = [
'subfleet_id' => 'integer', 'subfleet_id' => 'integer',
'mtow' => 'float',
'zfw' => 'float', 'zfw' => 'float',
'flight_time' => 'float', 'flight_time' => 'float',
'state' => 'integer', 'state' => 'integer',
@@ -62,6 +66,8 @@ class Aircraft extends Model
'name' => 'required', 'name' => 'required',
'status' => 'required', 'status' => 'required',
'registration' => 'required', 'registration' => 'required',
'mtow' => 'nullable|numeric',
'zfw' => 'nullable|numeric',
]; ];
/** /**
-12
View File
@@ -1,12 +0,0 @@
<?php
namespace App\Models\Enums;
use App\Contracts\Enum;
class AnalyticsDimensions extends Enum
{
public const PHP_VERSION = 1;
public const DATABASE_VERSION = 2;
public const PHPVMS_VERSION = 3;
}
-14
View File
@@ -1,14 +0,0 @@
<?php
namespace App\Models\Enums;
use App\Contracts\Enum;
/**
* Metrics IDs used in Google Analytics
*/
class AnalyticsMetrics extends Enum
{
// Track the lookup time for airports from vaCentral
public const AIRPORT_LOOKUP_TIME = 1;
}
+7 -2
View File
@@ -6,6 +6,11 @@ use App\Contracts\Enum;
class PageType extends Enum class PageType extends Enum
{ {
public const HTML = 0; public const PAGE = 0;
public const MARKDOWN = 1; public const LINK = 1;
public static $labels = [
self::PAGE => 'Page',
self::LINK => 'Link',
];
} }

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