From 4a3ec38919ebfe66331bcf5487fd106a8f81faba Mon Sep 17 00:00:00 2001 From: Nabeel S Date: Fri, 27 Mar 2020 11:49:19 -0400 Subject: [PATCH] Option for SB only on bids; add the new file type #642 (#643) Option for SB only on bids; add the new file type #642 --- app/Database/seeds/settings.yml | 7 + .../Controllers/Frontend/FlightController.php | 38 +- app/Models/SimBriefXML.php | 15 + app/Services/SimBriefService.php | 58 ++- resources/lang/en/flights.php | 2 +- resources/lang/es/flights.php | 2 +- resources/lang/it/flights.php | 2 +- .../layouts/default/flights/bids.blade.php | 15 + .../layouts/default/flights/index.blade.php | 2 +- .../default/flights/simbrief_form.blade.php | 111 +++- .../layouts/default/flights/table.blade.php | 10 +- tests/SimBriefTest.php | 7 +- tests/TestCase.php | 50 +- tests/data/simbrief/acars_briefing.xml | 475 ++++++++++++++++++ tests/data/{ => simbrief}/briefing.xml | 8 + 15 files changed, 746 insertions(+), 56 deletions(-) create mode 100644 resources/views/layouts/default/flights/bids.blade.php create mode 100644 tests/data/simbrief/acars_briefing.xml rename tests/data/{ => simbrief}/briefing.xml (99%) diff --git a/app/Database/seeds/settings.yml b/app/Database/seeds/settings.yml index eea0e228..606bc67b 100644 --- a/app/Database/seeds/settings.yml +++ b/app/Database/seeds/settings.yml @@ -159,6 +159,13 @@ options: '' type: string description: 'Your SimBrief API key' +- key: simbrief.only_bids + name: 'Only allow for bids' + group: simbrief + value: true + options: '' + type: boolean + description: 'Only allow briefs to be created for bidded flights' - key: simbrief.expire_days name: 'SimBrief Expire Time' group: simbrief diff --git a/app/Http/Controllers/Frontend/FlightController.php b/app/Http/Controllers/Frontend/FlightController.php index 66fc542d..b0c3bb4a 100644 --- a/app/Http/Controllers/Frontend/FlightController.php +++ b/app/Http/Controllers/Frontend/FlightController.php @@ -9,11 +9,12 @@ use App\Repositories\AirportRepository; use App\Repositories\Criteria\WhereCriteria; use App\Repositories\FlightRepository; use App\Repositories\SubfleetRepository; +use App\Repositories\UserRepository; use App\Services\GeoService; -use Flash; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Log; +use Laracasts\Flash\Flash; use Prettus\Repository\Criteria\RequestCriteria; use Prettus\Repository\Exceptions\RepositoryException; @@ -24,6 +25,7 @@ class FlightController extends Controller private $flightRepo; private $subfleetRepo; private $geoSvc; + private $userRepo; /** * @param AirlineRepository $airlineRepo @@ -31,19 +33,22 @@ class FlightController extends Controller * @param FlightRepository $flightRepo * @param GeoService $geoSvc * @param SubfleetRepository $subfleetRepo + * @param UserRepository $userRepo */ public function __construct( AirlineRepository $airlineRepo, AirportRepository $airportRepo, FlightRepository $flightRepo, GeoService $geoSvc, - SubfleetRepository $subfleetRepo + SubfleetRepository $subfleetRepo, + UserRepository $userRepo ) { $this->airlineRepo = $airlineRepo; $this->airportRepo = $airportRepo; $this->flightRepo = $flightRepo; $this->geoSvc = $geoSvc; $this->subfleetRepo = $subfleetRepo; + $this->userRepo = $userRepo; } /** @@ -113,6 +118,7 @@ class FlightController extends Controller 'dep_icao' => $request->input('dep_icao'), 'subfleet_id' => $request->input('subfleet_id'), 'simbrief' => !empty(setting('simbrief.api_key')), + 'simbrief_bids' => setting('simbrief.only_bids'), ]); } @@ -125,19 +131,25 @@ class FlightController extends Controller */ public function bids(Request $request) { - $user = Auth::user(); + $user = $this->userRepo + ->with(['bids', 'bids.flight']) + ->find(Auth::user()->id); - $flights = $user->flights()->paginate(); - $saved_flights = $flights->pluck('id')->toArray(); + $flights = collect(); + $saved_flights = []; + foreach ($user->bids as $bid) { + $flights->add($bid->flight); + $saved_flights[] = $bid->flight->id; + } - return view('flights.index', [ - 'title' => trans_choice('flights.mybid', 2), - 'airlines' => $this->airlineRepo->selectBoxList(true), - 'airports' => $this->airportRepo->selectBoxList(true), - 'flights' => $flights, - 'saved' => $saved_flights, - 'subfleets' => $this->subfleetRepo->selectBoxList(true), - 'simbrief' => !empty(setting('simbrief.api_key')), + return view('flights.bids', [ + 'airlines' => $this->airlineRepo->selectBoxList(true), + 'airports' => $this->airportRepo->selectBoxList(true), + 'flights' => $flights, + 'saved' => $saved_flights, + 'subfleets' => $this->subfleetRepo->selectBoxList(true), + 'simbrief' => !empty(setting('simbrief.api_key')), + 'simbrief_bids' => setting('simbrief.only_bids'), ]); } diff --git a/app/Models/SimBriefXML.php b/app/Models/SimBriefXML.php index 3ed1b00a..c95d29fb 100644 --- a/app/Models/SimBriefXML.php +++ b/app/Models/SimBriefXML.php @@ -26,6 +26,21 @@ class SimBriefXML extends SimpleXMLElement return str_pad($fl, 3, '0', STR_PAD_LEFT); } + /** + * Return the URL to the vmsACARS flight plan file + * + * @return string|null + */ + public function getAcarsXmlUrl() + { + if (!empty($this->fms_downloads->vms)) { + $base_url = $this->fms_downloads->directory; + return $base_url.$this->fms_downloads->vms->link; + } + + return null; + } + /** * Retrieve all of the flightplans * diff --git a/app/Services/SimBriefService.php b/app/Services/SimBriefService.php index 37aa65d5..c47191e8 100644 --- a/app/Services/SimBriefService.php +++ b/app/Services/SimBriefService.php @@ -7,6 +7,7 @@ use App\Models\Acars; use App\Models\Enums\AcarsType; use App\Models\Pirep; use App\Models\SimBrief; +use App\Models\SimBriefXML; use Carbon\Carbon; use GuzzleHttp\Client as GuzzleClient; use GuzzleHttp\Exception\GuzzleException; @@ -31,7 +32,7 @@ class SimBriefService extends Service * * @return SimBrief|null */ - public function checkForOfp(string $user_id, string $ofp_id, string $flight_id): SimBrief + public function checkForOfp(string $user_id, string $ofp_id, string $flight_id) { $uri = str_replace('{id}', $ofp_id, config('phpvms.simbrief_url')); @@ -52,20 +53,27 @@ class SimBriefService extends Service $body = $response->getBody()->getContents(); + /** @var SimBriefXML $ofp */ + $ofp = simplexml_load_string($body, SimBriefXML::class); + $attrs = [ 'user_id' => $user_id, 'flight_id' => $flight_id, - 'ofp_xml' => $body, + 'ofp_xml' => $ofp->asXML(), ]; - // TODO: Retrieve the ACARS XML and store that. For now, replace the doctype + // Try to download the XML file for ACARS. If it doesn't work, try to modify the main OFP + $acars_xml = $this->getAcarsOFP($ofp); + if (empty($acars_xml)) { + $new_doctype = ''; + $acars_xml = str_replace('', $new_doctype, $body); + $acars_xml = str_replace('', '', $acars_xml); + $acars_xml = str_replace("\n", '', $acars_xml); - $new_doctype = ''; - $acars_xml = str_replace('', $new_doctype, $body); - $acars_xml = str_replace('', '', $acars_xml); - $acars_xml = str_replace("\n", '', $acars_xml); - - $attrs['acars_xml'] = simplexml_load_string($acars_xml)->asXML(); + $attrs['acars_xml'] = simplexml_load_string($acars_xml)->asXML(); + } else { + $attrs['acars_xml'] = $acars_xml->asXML(); + } // Save this into the Simbrief table, if it doesn't already exist return SimBrief::updateOrCreate( @@ -74,6 +82,38 @@ class SimBriefService extends Service ); } + /** + * @param \App\Models\SimBriefXML $ofp + * + * @return \SimpleXMLElement|null + */ + public function getAcarsOFP(SimBriefXML $ofp) + { + $url = $ofp->getAcarsXmlUrl(); + if (empty($url)) { + return null; + } + + $opts = [ + 'connect_timeout' => 2, // wait two seconds by default + 'allow_redirects' => true, + ]; + + try { + $response = $this->httpClient->request('GET', $url, $opts); + if ($response->getStatusCode() !== 200) { + return null; + } + } catch (GuzzleException $e) { + Log::error('Simbrief HTTP Error: '.$e->getMessage()); + dd($e); + return null; + } + + $body = $response->getBody()->getContents(); + return simplexml_load_string($body); + } + /** * Create a prefiled PIREP from a given brief. * diff --git a/resources/lang/en/flights.php b/resources/lang/en/flights.php index cf6afbbe..92fb7236 100644 --- a/resources/lang/en/flights.php +++ b/resources/lang/en/flights.php @@ -6,7 +6,7 @@ return [ 'flighttype' => 'Flight Type', 'flighthours' => 'Flight Hours', 'route' => 'Route', - 'mybid' => 'My Bid|My Bids', + 'mybid' => 'My Bids', 'search' => 'Search', 'addremovebid' => 'Add/Remove Bid', 'bidremoved' => 'Your bid was removed.', diff --git a/resources/lang/es/flights.php b/resources/lang/es/flights.php index d4393879..792eaf66 100644 --- a/resources/lang/es/flights.php +++ b/resources/lang/es/flights.php @@ -6,7 +6,7 @@ return [ 'flighttype' => 'Tipo de vuelo', 'flighthours' => 'Horas de vuelo', 'route' => 'Ruta', - 'mybid' => 'Mi reserva|Mis reservas', + 'mybid' => 'Mis reservas', 'search' => 'Buscar', 'addremovebid' => 'Añadir/Quitar reserva', 'bidremoved' => 'Tu reserva ha sido eliminada.', diff --git a/resources/lang/it/flights.php b/resources/lang/it/flights.php index 2ee71cd2..986e6377 100644 --- a/resources/lang/it/flights.php +++ b/resources/lang/it/flights.php @@ -6,7 +6,7 @@ return [ 'flighttype' => 'Tipo di Volo', 'flighthours' => 'Ore di Volo', 'route' => 'Rotta', - 'mybid' => 'Mia prenotazione|Mie Prenotazioni', + 'mybid' => 'Mie Prenotazioni', 'addremovebid' => 'Aggiungi/Rimuovi Prenotazione', 'bidremoved' => 'La tua prenotazione è stata rimossa.', 'bidadded' => 'La tua prenotazione è stata aggiunta.', diff --git a/resources/views/layouts/default/flights/bids.blade.php b/resources/views/layouts/default/flights/bids.blade.php new file mode 100644 index 00000000..e5625b1e --- /dev/null +++ b/resources/views/layouts/default/flights/bids.blade.php @@ -0,0 +1,15 @@ +@extends('app') +@section('title', __('flights.mybid')) + +@section('content') +
+ @include('flash::message') +
+

{{ __('flights.mybid') }}

+ @include('flights.table') +
+
+@endsection + +@include('flights.scripts') + diff --git a/resources/views/layouts/default/flights/index.blade.php b/resources/views/layouts/default/flights/index.blade.php index c93b9ba5..46dd4860 100644 --- a/resources/views/layouts/default/flights/index.blade.php +++ b/resources/views/layouts/default/flights/index.blade.php @@ -5,7 +5,7 @@
@include('flash::message')
-

{{ $title ?? trans_choice('common.flight', 2) }}

+

{{ trans_choice('common.flight', 2) }}

@include('flights.table')
diff --git a/resources/views/layouts/default/flights/simbrief_form.blade.php b/resources/views/layouts/default/flights/simbrief_form.blade.php index 9607876a..25fc0e96 100644 --- a/resources/views/layouts/default/flights/simbrief_form.blade.php +++ b/resources/views/layouts/default/flights/simbrief_form.blade.php @@ -39,8 +39,115 @@
diff --git a/resources/views/layouts/default/flights/table.blade.php b/resources/views/layouts/default/flights/table.blade.php index 0a179809..c2803195 100644 --- a/resources/views/layouts/default/flights/table.blade.php +++ b/resources/views/layouts/default/flights/table.blade.php @@ -71,10 +71,12 @@
@if ($simbrief !== false) - - Create SimBrief Flight Plan - + @if ($simbrief_bids === false || ($simbrief_bids === true && in_array($flight->id, $saved, true))) + + Create SimBrief Flight Plan + + @endif @endif 'OMDB', ]); - $this->mockXmlResponse('briefing.xml'); + $this->mockXmlResponse([ + 'simbrief/briefing.xml', + 'simbrief/acars_briefing.xml', + ]); /** @var SimBriefService $sb */ $sb = app(SimBriefService::class); @@ -44,7 +47,7 @@ class SimBriefTest extends TestCase // Spot check reading of the files $files = $briefing->files; - $this->assertEquals(45, $files->count()); + $this->assertEquals(47, $files->count()); $this->assertEquals( 'http://www.simbrief.com/ofp/flightplans/OMAAOMDB_PDF_1584226092.pdf', $files->firstWhere('name', 'PDF Document')['url'] diff --git a/tests/TestCase.php b/tests/TestCase.php index 5a97d530..a08caa78 100755 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -132,19 +132,22 @@ class TestCase extends Illuminate\Foundation\Testing\TestCase /** * Return a mock Guzzle Client with a response loaded from $mockFile * - * @param $mockFile + * @param array|string $files */ - public function mockGuzzleClient($mockFile): void + public function mockGuzzleClient($files): void { - $mock = new MockHandler([ - new Response( - 200, - [ - 'Content-Type' => 'application/json; charset=utf-8', - ], - $this->readDataFile($mockFile) - ), - ]); + if (!is_array($files)) { + $files = [$files]; + } + + $responses = []; + foreach ($files as $file) { + $responses[] = new Response(200, [ + 'Content-Type' => 'application/json; charset=utf-8', + ], $this->readDataFile($file)); + } + + $mock = new MockHandler($responses); $handler = HandlerStack::create($mock); $guzzleClient = new Client(['handler' => $handler]); @@ -152,19 +155,22 @@ class TestCase extends Illuminate\Foundation\Testing\TestCase } /** - * @param string $filename + * @param array|string $files The filename or files to respond with */ - public function mockXmlResponse($filename) + public function mockXmlResponse($files) { - $mock = new MockHandler([ - new Response( - 200, - [ - 'Content-Type' => 'text/xml', - ], - $this->readDataFile($filename) - ), - ]); + if (!is_array($files)) { + $files = [$files]; + } + + $responses = []; + foreach ($files as $file) { + $responses[] = new Response(200, [ + 'Content-Type' => 'text/xml', + ], $this->readDataFile($file)); + } + + $mock = new MockHandler($responses); $handler = HandlerStack::create($mock); $guzzleClient = new Client(['handler' => $handler]); diff --git a/tests/data/simbrief/acars_briefing.xml b/tests/data/simbrief/acars_briefing.xml new file mode 100644 index 00000000..aa62dd9b --- /dev/null +++ b/tests/data/simbrief/acars_briefing.xml @@ -0,0 +1,475 @@ + + + + 19722791 + 120867 + 1585313544 + lido2 + 2001 + lbs + + + 1 + VMS + 99 + 0 + PAYLOAD/CARGO LIMITED BY MLW + + 1 + CI5 + 250/300/78 + 78/300/250 + CI0 + RES + 5 + 23000 + MKJP/0230 + 11 + 56792 + 12 + 064 + 018 + 273 + 319 + 307 + 5723 + 388 + .63 + 171 + LEXUV3 KEMBO G633 NALRO GUBEL3 + LEXUV3 KEMBO G633 NALRO GUBEL3 + LEXUV3 KEMBO G633 NALRO GUBEL3 + + + MKJP + KIN + + 18 + 17.935556 + -76.787500 + NORMAN MANLEY INTL + 12 + + + MWCR + GCM + + 8 + 19.292781 + -81.357767 + ROBERTS INTL + 08 + + + MKJS + MBJ + + 4 + 18.503669 + -77.913389 + SANGSTER INTL + 07 + 31000 + 232 + 201 + 233 + 103 + 109 + 411 + 410 + M001 + 018 + 018 + 57000 + P12 + 2575 + 4302 + NALRO2 NALRO DCT OTEKO DCT IMONI OMAXI5 + NALRO2 NALRO DCT OTEKO DCT IMONI OMAXI5 + + + + + + UKIMO + UKIMO + wpt + 17.918556 + -76.743300 + CLB + LEXUV3 + 1 + 5 + 112 + 119 + 111 + 118 + 4900 + + + PEMPE + PEMPE + wpt + 17.809956 + -76.789128 + CLB + LEXUV3 + 1 + 7 + 201 + 210 + 199 + 207 + 10800 + + + LEXUV + LEXUV + wpt + 17.853819 + -76.902525 + CLB + LEXUV3 + 1 + 7 + 292 + 300 + 293 + 301 + 14200 + + + KEMBO + KEMBO + wpt + 18.218889 + -77.354722 + CLB + LEXUV3 + 0 + 34 + 310 + 318 + 311 + 319 + 22200 + + + TOC + TOP OF CLIMB + ltlg + 18.288425 + -77.494553 + CLB + G633 + 0 + 9 + 297 + 305 + 298 + 306 + 23000 + + + SIA + SANGSTER + vor + 18.501047 + -77.924100 + CRZ + G633 + 0 + 28 + 297 + 305 + 298 + 305 + 23000 + + + PETSI + PETSI + wpt + 18.660278 + -78.595833 + CRZ + G633 + 0 + 39 + 284 + 291 + 285 + 292 + 23000 + + + FROST + FROST + wpt + 18.756944 + -79.009167 + CRZ + G633 + 0 + 24 + 283 + 291 + 284 + 291 + 23000 + + + OTEKO + OTEKO + wpt + 18.870278 + -79.500000 + CRZ + G633 + 0 + 29 + 283 + 290 + 285 + 292 + 23000 + + + NALRO + NALRO + wpt + 19.030822 + -80.206147 + CRZ + G633 + 0 + 41 + 283 + 290 + 285 + 291 + 23000 + + + TOD + TOP OF DESCENT + ltlg + 19.126848 + -80.634858 + CRZ + GUBEL3 + 1 + 25 + 283 + 289 + 286 + 292 + 23000 + + + D107Q + D107Q + wpt + 19.225436 + -81.080228 + DSC + GUBEL3 + 1 + 26 + 283 + 288 + 285 + 290 + 10500 + + + D080O + D080O + wpt + 19.350150 + -81.115561 + DSC + GUBEL3 + 1 + 8 + 345 + 350 + 348 + 353 + 6700 + + + GUBEL + GUBEL + wpt + 19.338075 + -81.166667 + DSC + GUBEL3 + 1 + 3 + 255 + 261 + 255 + 260 + 5300 + + + MWCR + ROBERTS INTL + apt + 19.292781 + -81.357767 + DSC + GUBEL3 + 1 + 34 + 255 + 261 + 255 + 260 + 2500 + + + + (FPL-VMS99-IS +-A320/M-SDE3FGHIRWY/LB1 +-MKJP1230 +-N0388F230 LEXUV3 KEMBO G633 NALRO GUBEL3 +-MWCR0100 MKJS +-PBN/A1B1C1D1O1S1 DOF/140101 REG/N320SB OPR/VMS PER/C RMK/TCAS) + N0388F230 LEXUV3 KEMBO G633 NALRO GUBEL3 + N0388F230 LEXUV3 KEMBO G633 NALRO GUBEL3 + VMS99 + 0388 + N + 230 + F + PBN/A1B1C1D1O1S1 DOF/140101 REG/N320SB OPR/VMS PER/C RMK/TCAS + MKJK + MKJK + MKJK + + + + + A320 + 320 + A320-200 + N320SB + 205 + + M-SDE3FGHIRWY/LB1 + 180 + 1 + + + 220 + 5723 + 1411 + 4302 + 3967 + 0 + 0 + 15403 + 15403 + 15623 + 9900 + 5643 + 42600 + + + 3651 + 7620 + 1388579400 + 1388579700 + 1388587320 + 1388587500 + 8100 + 1388579400 + 1388579700 + 1388583351 + 1388583531 + 4131 + -5 + -5 + 300 + 180 + 2700 + 10496 + 900 + 0 + 0 + + + 96518 + 171 + 230 + 0 + 39307 + 135825 + 137789 + 151228 + 151228 + 171961 + L + 145505 + 145505 + 151448 + + + VMS + 99 + A320 + MKJP + MWCR + 1388534400 + 43200 + 1800 + LEXUV3 KEMBO G633 NALRO GUBEL3 + 7200 + 900 + + + + auto + MKJS + + NABEEL SHAHZAD + 120867 + 1 + auto + 0 + auto + 45 + auto + auto + auto + auto + auto + auto + auto + auto + AUTO + lido + 1 + 1 + 0 + 1 + 1 + 1 + 0 + 1 + + + + + + + + + + false + + + diff --git a/tests/data/briefing.xml b/tests/data/simbrief/briefing.xml similarity index 99% rename from tests/data/briefing.xml rename to tests/data/simbrief/briefing.xml index 16387d9d..3c6359d5 100644 --- a/tests/data/briefing.xml +++ b/tests/data/simbrief/briefing.xml @@ -4277,6 +4277,10 @@ NIL X-Plane 9/10 OMAAOMDB_XP9_1584226092.fms + + phpVMS ACARS + MKJPMWCR_VMS_1585313544.xml + http://www.simbrief.com/ofp/flightplans/ @@ -4460,6 +4464,10 @@ NIL X-Plane 9/10 OMAAOMDB_XP9_1584226092.fms + + phpVMS ACARS + MKJPMWCR_VMS_1585313544.xml + http://www.simbrief.com/ofp/uads/