Merge pull request #306 from nabeelio/issue-297/search-options

Add more search criteria/dev environment via docker-compose #297
This commit is contained in:
Nabeel Shahzad
2019-05-11 14:47:37 -05:00
committed by GitHub
22 changed files with 326 additions and 59 deletions

View File

@@ -55,6 +55,7 @@ if [ "$TRAVIS" = "true" ]; then
.sass-cache
.idea
.travis
docker
tests
_ide_helper.php
.dpl
@@ -64,6 +65,7 @@ if [ "$TRAVIS" = "true" ]; then
.styleci.yml
env.php
config.php
docker-compose.yml
Makefile
phpunit.xml
phpvms.iml

View File

@@ -52,7 +52,7 @@ update: build
@echo "Done!"
.PHONY: reset
reset: cleanapp/Models/Traits/JournalTrait.php
reset: clean
@php $(COMPOSER) dump-autoload
@make reload-db

View File

@@ -1,5 +1,5 @@
dnsmasq: /usr/local/sbin/dnsmasq --keep-in-foreground
#dnsmasq: /usr/local/sbin/dnsmasq --keep-in-foreground
php-fpm: /usr/local/sbin/php-fpm --nodaemonize
nginx: /usr/local/bin/nginx -g 'daemon off;'
#mysql: /usr/local/bin/mysqld
mysql: docker-compose --file ~/docker/mysql/docker-compose.yml up
#mailhog: /usr/local/bin/mailhog

View File

@@ -2,16 +2,15 @@
[![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&utm_medium=referral&utm_content=nabeelio/phpvms&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. If you're looking for
the old, phpVMS classic, it's [available here](https://github.com/nabeelio/phpvms_v2).
The next phpvms version built on the laravel framework. work in progress. The latest documentation, with installation instructions is available
[on the phpVMS documentation](http://docs.phpvms.net/) page.
# installation
A full distribution, with all of the composer dependencies, is available at this
[GitHub Releases](https://github.com/nabeelio/phpvms/releases) link.
The latest documentation, with installation instructions is available
[on the phpVMS documentation](http://docs.phpvms.net/) page.
## Requirements
@@ -30,6 +29,22 @@ The latest documentation, with installation instructions is available
## Installer
1. Upload to your server
2. 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)
# development environment
A full development environment can be brought up using Docker:
```bash
composer install
npm install
docker-compose up
```
Then go to `http://localhost`. If you're using dnsmasq, the `app` container is listening on `phpvms.test`, or you can add to your `/etc/hosts` file:
```
127.0.0.1 phpvms.test
```

View File

@@ -22,7 +22,7 @@ $factory->define(App\Models\Flight::class, function (Faker $faker) {
'alt_airport_id' => function () {
return factory(App\Models\Airport::class)->create()->id;
},
'distance' => $faker->numberBetween(0, 3000),
'distance' => $faker->numberBetween(0, 1000),
'route' => null,
'level' => 0,
'dpt_time' => $faker->time(),
@@ -35,7 +35,7 @@ $factory->define(App\Models\Flight::class, function (Faker $faker) {
'start_date' => null,
'end_date' => null,
'created_at' => $faker->dateTimeBetween('-1 week', 'now'),
'updated_at' => function (array $flight) {
'updated_at' => static function (array $flight) {
return $flight['created_at'];
},
];

View File

@@ -89,31 +89,37 @@ class FlightController extends Controller
*/
public function search(Request $request)
{
$user = Auth::user();
try {
$where = [
'active' => true,
'visible' => true,
];
$where = [
'active' => true,
'visible' => true,
];
// Allow the option to bypass some of these restrictions for the searches
if (!$request->filled('ignore_restrictions')
|| $request->get('ignore_restrictions') === '0'
) {
if (setting('pilots.restrict_to_company')) {
$where['airline_id'] = Auth::user()->airline_id;
}
if (setting('pilots.only_flights_from_current')) {
$where['dpt_airport_id'] = Auth::user()->curr_airport_id;
}
}
try {
$this->flightRepo->resetCriteria();
$this->flightRepo->searchCriteria($request);
$this->flightRepo->pushCriteria(new RequestCriteria($request));
$this->flightRepo->pushCriteria(new WhereCriteria($request, $where));
$this->flightRepo->pushCriteria(new RequestCriteria($request));
$flights = $this->flightRepo->paginate();
} catch (RepositoryException $e) {
return response($e, 503);
}
foreach ($flights as $flight) {
$this->flightSvc->filterSubfleets($user, $flight);
$this->flightSvc->filterSubfleets(Auth::user(), $flight);
}
return FlightResource::collection($flights);

View File

@@ -13,6 +13,7 @@ use Flash;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Log;
use Prettus\Repository\Criteria\RequestCriteria;
use Prettus\Repository\Exceptions\RepositoryException;
/**
@@ -68,6 +69,7 @@ class FlightController extends Controller
try {
$this->flightRepo->pushCriteria(new WhereCriteria($request, $where));
$this->flightRepo->pushCriteria(new RequestCriteria($request));
} catch (RepositoryException $e) {
Log::emergency($e);
}
@@ -137,6 +139,8 @@ class FlightController extends Controller
$where['dpt_airport_id'] = Auth::user()->curr_airport_id;
}
$this->flightRepo->resetCriteria();
try {
$this->flightRepo->pushCriteria(new WhereCriteria($request, $where));
} catch (RepositoryException $e) {

View File

@@ -5,6 +5,7 @@ namespace App\Http\Controllers\Frontend;
use App\Interfaces\Controller;
use App\Models\User;
use Illuminate\Database\QueryException;
use Log;
/**
* Class HomeController
@@ -18,10 +19,21 @@ class HomeController extends Controller
{
try {
$users = User::orderBy('created_at', 'desc')->take(4)->get();
debug($users);
} catch (\PDOException $e) {
Log::emergency($e);
return view('system/errors/database_error', [
'error' => $e->getMessage(),
]);
} catch (QueryException $e) {
return view('system/errors/not_installed');
}
// No users
if (!$users) {
return view('system/errors/not_installed');
}
return view('home', [
'users' => $users,
]);

View File

@@ -18,6 +18,12 @@ class WhereCriteria implements CriteriaInterface
protected $request;
protected $where;
/**
* Create a new Where search.
*
* @param $request
* @param $where
*/
public function __construct($request, $where)
{
$this->request = $request;

View File

@@ -18,15 +18,16 @@ class FlightRepository extends Repository implements CacheableInterface
protected $fieldSearchable = [
'arr_airport_id',
'distance',
'dpt_airport_id',
'flight_number' => 'like',
'flight_code' => 'like',
'flight_leg' => 'like',
'route_code' => 'like',
'route_leg' => 'like',
'route' => 'like',
'notes' => 'like',
];
public function model()
public function model(): string
{
return Flight::class;
}
@@ -70,7 +71,7 @@ class FlightRepository extends Repository implements CacheableInterface
*
* @return $this
*/
public function searchCriteria(Request $request, bool $only_active = true)
public function searchCriteria(Request $request, bool $only_active = true): self
{
$where = [];
@@ -103,6 +104,16 @@ class FlightRepository extends Repository implements CacheableInterface
$where['arr_airport_id'] = $request->arr_icao;
}
// Distance, greater than
if ($request->filled('dgt')) {
$where[] = ['distance', '>=', $request->dgt];
}
// Distance, less than
if ($request->filled('dlt')) {
$where[] = ['distance', '<=', $request->dlt];
}
$this->pushCriteria(new WhereCriteria($request, $where));
return $this;

View File

@@ -1,5 +1,8 @@
<?php
use App\Exceptions\SettingNotFound;
use Illuminate\Contracts\View\Factory;
if (!function_exists('in_mask')) {
/**
* Return true/false if a value exists in a mask
@@ -109,7 +112,7 @@ if (!function_exists('skin_view')) {
* @param array $vars
* @param array $merge_data
*
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
* @return Factory|\Illuminate\View\View
*/
function skin_view($template, array $vars = [], array $merge_data = [])
{
@@ -136,7 +139,7 @@ if (!function_exists('setting')) {
try {
$value = $settingRepo->retrieve($key);
} catch (\App\Exceptions\SettingNotFound $e) {
} catch (SettingNotFound $e) {
return $default;
}

View File

@@ -14,40 +14,41 @@
"ext-pdo": "*",
"composer/composer": "1.8.x",
"composer/semver": "1.4.x",
"laravel/framework": "5.7.x",
"laravelcollective/html": "5.7.x",
"prettus/l5-repository": "2.6.x",
"nwidart/laravel-modules": "3.3.x",
"santigarcor/laratrust": "5.0.x",
"arrilot/laravel-widgets": "3.13.x",
"sebastiaanluca/laravel-helpers": "1.0.x",
"joshbrw/laravel-module-installer": "0.1.x",
"webpatser/laravel-uuid": "3.x",
"igaster/laravel-theme": "2.0.x",
"irazasyed/laravel-gamp": "1.3.x",
"toin0u/geotools-laravel": "1.0.x",
"spatie/laravel-pjax": "1.3.x",
"myclabs/deep-copy": "1.8.x",
"league/geotools": "0.8.x",
"fzaninotto/faker": "^1.8",
"hashids/hashids": "2.0.x",
"jackiedo/timezonelist": "5.x",
"tivie/php-os-detector": "1.1.x",
"pragmarx/version": "0.2.x",
"guzzlehttp/guzzle": "6.3.x",
"jmikola/geojson": "1.0.x",
"laracasts/flash": "3.0.x",
"nabeel/vacentral": "1.x",
"league/iso3166": "2.1.x",
"theiconic/php-ga-measurement-protocol": "2.7.x",
"vierbergenlars/php-semver": "3.0.x",
"php-units-of-measure/php-units-of-measure": "2.1.x",
"markrogoyski/math-php": "^0.38.0",
"akaunting/money": "1.0.x",
"anhskohbo/no-captcha": "3.0.x",
"league/csv": "9.2.x",
"arrilot/laravel-widgets": "3.13.x",
"fzaninotto/faker": "^1.8",
"guzzlehttp/guzzle": "6.3.x",
"hashids/hashids": "2.0.x",
"igaster/laravel-theme": "2.0.x",
"intervention/image": "2.4.x",
"waavi/sanitizer": "1.0.x"
"irazasyed/laravel-gamp": "1.3.x",
"jackiedo/timezonelist": "5.x",
"jmikola/geojson": "1.0.x",
"joshbrw/laravel-module-installer": "0.1.x",
"laracasts/flash": "3.0.x",
"laravel/framework": "5.7.x",
"laravelcollective/html": "5.7.x",
"league/csv": "9.2.x",
"league/geotools": "0.8.x",
"league/iso3166": "2.1.x",
"markrogoyski/math-php": "^0.38.0",
"myclabs/deep-copy": "1.8.x",
"nabeel/vacentral": "1.x",
"nwidart/laravel-modules": "3.3.x",
"php-units-of-measure/php-units-of-measure": "2.1.x",
"pragmarx/version": "0.2.x",
"prettus/l5-repository": "2.6.x",
"santigarcor/laratrust": "5.0.x",
"sebastiaanluca/laravel-helpers": "1.0.x",
"spatie/laravel-pjax": "1.3.x",
"symfony/polyfill-iconv": "^1.11",
"theiconic/php-ga-measurement-protocol": "2.7.x",
"tivie/php-os-detector": "1.1.x",
"toin0u/geotools-laravel": "1.0.x",
"vierbergenlars/php-semver": "3.0.x",
"waavi/sanitizer": "1.0.x",
"webpatser/laravel-uuid": "3.x"
},
"require-dev": {
"phpunit/phpunit": "7.5.x",

2
composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "fb105f6d95ca2218f8e3e03c93371cd3",
"content-hash": "290bc8970d44a12e8546926949d73e20",
"packages": [
{
"name": "akaunting/money",

48
docker-compose.yml Normal file
View File

@@ -0,0 +1,48 @@
---
version: '3'
services:
app:
build:
context: ./docker/php
environment:
DB_HOST: mysql
volumes:
- ./:/var/www
- ./docker/php/www.conf:/usr/local/etc/php-fpm.d/www.conf
depends_on:
- mysql
nginx:
image: nginx:1.13.8
command: /bin/bash -c "exec nginx -g 'daemon off;'"
volumes:
- ./:/var/www
- ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
ports:
- 80:80
depends_on:
- app
mysql:
image: mysql:5.7.26
environment:
MYSQL_DATABASE: phpvms
MYSQL_USER: phpvms
MYSQL_PASSWORD: phpvms
MYSQL_ROOT_PASSWORD:
MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'
volumes:
- ./docker/data/mysql:/var/lib/mysql
ports:
- 3306:3306
# Use this to tail the logs so it's just all in a single window
logs:
image: busybox
command: tail -f -F -n 0 /var/www/storage/logs/laravel.log
restart: always
volumes:
- ./storage:/var/www/storage
depends_on:
- app

2
docker/data/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
*
!.gitignore

27
docker/nginx/default.conf Normal file
View File

@@ -0,0 +1,27 @@
server {
listen 80 default_server;
server_name phpvms.test;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
root /var/www/public;
index index.php index.html index.htm;
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass app:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include /etc/nginx/fastcgi_params;
}
location ~ /\.ht {
deny all;
}
}

12
docker/php/Dockerfile Normal file
View File

@@ -0,0 +1,12 @@
FROM php:7.3-fpm
RUN apt-get update
RUN apt-get install -y libgmp-dev
RUN ln -sf /dev/stderr /var/log/fpm-error.log
RUN docker-php-ext-install \
mysqli \
pdo \
pdo_mysql \
gmp

15
docker/php/www.conf Normal file
View File

@@ -0,0 +1,15 @@
[www]
user = www-data
group = www-data
listen = :9000
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
php_flag[display_errors] = on
php_admin_flag[log_errors] = on

View File

@@ -1,7 +1,7 @@
<?php
/**
* phpVMS
* phpVMS (root folder)
*/
$path_to_phpvms_folder = __DIR__;

View File

@@ -62,7 +62,7 @@
<div class="row">
<div class="col-12">
<h2>Database Error</h2>
@yield('content')
{{ $error }}
</div>
</div>
</div>

64
swagger.yml Normal file
View File

@@ -0,0 +1,64 @@
---
swagger: "2.0"
info:
version: "7.0"
title: phpVMS API
description: All of the responses are contained in the "data" variable
basePath: /api/v1
schemes:
- https
paths:
"/flights/search":
get:
summary: Retrieve all the applications and flags
operationId: getFlightSearch
parameters:
- name: flight_id
in: query
type: string
required: false
description: ID of the flight
- name: airline_id
in: query
type: string
required: false
description: ID of the airline
- name: flight_number
in: query
type: string
required: false
description: Flight number to use
- name: route_code
in: query
type: string
required: false
description: The route code
- name: dep_icao
in: query
type: string
required: false
description: The departure ICAO
- name: arr_icao
in: query
type: string
required: false
description: The arrival ICAO
- name: dgt
in: query
type: integer
required: false
description: Flights with a distance greater than
- name: dgt
in: query
type: integer
required: false
description: Flights with a distance greater than
produces:
- application/json
responses:
200:
description: Returns flights from a search
schema:
$ref: '#/definitions/AppsWrapper'
tags:
- flights

View File

@@ -342,6 +342,45 @@ class FlightTest extends TestCase
$this->assertEquals($flight->id, $body['data'][0]['id']);
}
public function testFlightSearchApiDistance()
{
$total_flights = 10;
$this->user = factory(App\Models\User::class)->create();
$flights = factory(App\Models\Flight::class, $total_flights)->create([
'airline_id' => $this->user->airline_id,
]);
// Max distance generated in factory is 1000, so set a random flight
// and try to find it again through the search
$flight = $flights->random();
$flight->distance = 1500;
$flight->save();
$distance_gt = 1100;
$distance_lt = 1600;
// look for all of the flights now less than the "factory default" of 1000
$query = 'dlt=1000&ignore_restrictions=1';
$req = $this->get('/api/flights/search?'.$query);
$body = $req->json();
$this->assertCount($total_flights - 1, $body['data']);
// Try using greater than
$query = 'dgt='.$distance_gt.'&ignore_restrictions=1';
$req = $this->get('/api/flights/search?'.$query);
$body = $req->json();
$this->assertCount(1, $body['data']);
$this->assertEquals($flight->id, $body['data'][0]['id']);
$query = 'dgt='.$distance_gt.'&dlt='.$distance_lt.'&ignore_restrictions=1';
$req = $this->get('/api/flights/search?'.$query);
$body = $req->json();
$this->assertCount(1, $body['data']);
$this->assertEquals($flight->id, $body['data'][0]['id']);
}
public function testAddSubfleet()
{
$subfleet = factory(App\Models\Subfleet::class)->create();