diff --git a/.gitignore b/.gitignore index 059a517..d532d33 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,5 @@ Homestead.json Homestead.yaml .env + +tests/_output/* \ No newline at end of file diff --git a/app/Http/Controllers/AirportController.php b/app/Http/Controllers/AirportController.php index ae52325..ec4ee02 100644 --- a/app/Http/Controllers/AirportController.php +++ b/app/Http/Controllers/AirportController.php @@ -45,10 +45,11 @@ class AirportController extends Controller public function resourceList(Request $request) { $client = Client::create(); + $collection = $client->listAirports($request->input('autocomplete')); + + //add pagination $per_page = $request->input('per_page', 10); $page = $request->input('page', 1); - - $collection = $client->listAirports($request->input('autocomplete')); $paginator = new LengthAwarePaginator( $collection->forPage($page, $per_page), $collection->count(), @@ -56,8 +57,8 @@ class AirportController extends Controller $page ); - $airports = new Collection($paginator, new AirportTransformer(), 'airports'); - $airports->setPaginator(new IlluminatePaginatorAdapter($paginator)); + $airports = (new Collection($paginator, new AirportTransformer(), 'airports')) + ->setPaginator(new IlluminatePaginatorAdapter($paginator)); return $this->JsonApiResponse($airports, 200); } diff --git a/app/Http/Controllers/FlightController.php b/app/Http/Controllers/FlightController.php new file mode 100644 index 0000000..1d52157 --- /dev/null +++ b/app/Http/Controllers/FlightController.php @@ -0,0 +1,77 @@ +JsonApiResponse($result, 200); + } + + public function getFlight(Request $request, $id) + { + $flight = Flights::find($id); + + $result = new Item($flight, new FlightTransform(), 'flights'); + + return $this->JsonApiResponse($result, 200); + } + + public function removeFlight(Request $request, $id) + { + /** @var \App\Libraries\Trips\Models\Flights $flight */ + $flight = Flights::find($id); + $deleted = $flight->delete(); + +// $result = new Item($flight, [ +// 'id' => $id, +// 'message' => 'flight removed' +// ], 'message'); + $result = new Item($flight, new FlightTransform(), 'flights'); + + return $this->JsonApiResponse($result, 200); + } + + /** + * Convert the response to Json + * + * @param \League\Fractal\Resource\Item $resource + * @param $statusCode + * @return \Illuminate\Http\JsonResponse + */ + protected function JsonApiResponse(ResourceInterface $resource, $statusCode) + { + $manager = new Manager(); + $manager->setSerializer(new JsonApiSerializer('http://docker.dev:8080')); + $manager->parseIncludes('flights'); + + return response()->json($manager->createData($resource)->toArray(), $statusCode); + } +} diff --git a/app/Http/Controllers/TripController.php b/app/Http/Controllers/TripController.php new file mode 100644 index 0000000..772db70 --- /dev/null +++ b/app/Http/Controllers/TripController.php @@ -0,0 +1,100 @@ +input('per_page', 10); + $page = $request->input('page', 1); + $paginator = new LengthAwarePaginator( + $tripsCollection->forPage($page, $per_page), + $tripsCollection->count(), + $per_page, + $page + ); + + $result = (new Collection($paginator, new TripTransformer(), 'trips')) + ->setPaginator(new IlluminatePaginatorAdapter($paginator)); + + return $this->JsonApiResponse($result, 200); + } + + public function getTrip(Request $request, $id) + { + $trip = Trips::find($id); + + if (! $trip) { + return $this->returnErrorMessage("trip id $id not found", 400); + } + + $result = new Item($trip, new TripTransformer(), 'trips'); + + return $this->JsonApiResponse($result, 200, 'flights'); + } + + public function addFlight(Request $request, $id) + { + $trip = Trips::find($id); + $destination = $request->input('destination'); + + if (! $destination) { + return $this->returnErrorMessage('destination not set', 400); + } + + $flight = new Flights(['destination' => $destination]); + $flight->save(); + $trip->flights()->attach($flight->id); + + $result = new Item($trip, new TripTransformer(), 'trips'); + return $this->JsonApiResponse($result, 201, 'flights'); + } + + /** + * Convert the response to Json + * + * @param \League\Fractal\Resource\Item $resource + * @param $statusCode + * @return \Illuminate\Http\JsonResponse + */ + protected function JsonApiResponse(ResourceInterface $resource, $statusCode, $includes = '') + { + $manager = new Manager(); + $manager->setSerializer(new JsonApiSerializer('http://docker.dev:8080')); + $manager->parseIncludes($includes); + + return response()->json($manager->createData($resource)->toArray(), $statusCode); + } + + protected function returnErrorMessage($message, $statusCode = 400) + { + return response()->json([ + 'error_message' => $message + ], $statusCode); + } +} diff --git a/app/Libraries/Trips/FlightTransform.php b/app/Libraries/Trips/FlightTransform.php new file mode 100644 index 0000000..0f091f1 --- /dev/null +++ b/app/Libraries/Trips/FlightTransform.php @@ -0,0 +1,26 @@ + $flight->id, + 'name' => $flight->destination, + 'links' => [ + 'rel' => 'self', + 'uri' => '/flights/'.$flight->id, + ] + ]; + } +} diff --git a/app/Libraries/Trips/Models/Flights.php b/app/Libraries/Trips/Models/Flights.php new file mode 100644 index 0000000..f0d1184 --- /dev/null +++ b/app/Libraries/Trips/Models/Flights.php @@ -0,0 +1,24 @@ +belongsToMany(Trips::class, 'trip_flights'); + } + + public function toArray() + { + return [ + 'id' => $this->id, + 'destination' => $this->destination, + ]; + } +} diff --git a/app/Libraries/Trips/Models/Trips.php b/app/Libraries/Trips/Models/Trips.php new file mode 100644 index 0000000..3e28c99 --- /dev/null +++ b/app/Libraries/Trips/Models/Trips.php @@ -0,0 +1,19 @@ +belongsToMany(Flights::class, 'trip_flights'); + } +} diff --git a/app/Libraries/Trips/TripTransformer.php b/app/Libraries/Trips/TripTransformer.php new file mode 100644 index 0000000..d992810 --- /dev/null +++ b/app/Libraries/Trips/TripTransformer.php @@ -0,0 +1,49 @@ + $trip->id, + 'name' => $trip->name, + 'updated_at' => $trip->updated_at, + 'flights' => $trip->flights()->get(), + 'links' => [ + 'rel' => 'self', + 'uri' => '/trips/'.$trip->code, + ] + ]; + } + + /** + * Include Author + * + * @return \League\Fractal\Resource\ResourceAbstract + */ + public function includeFlights(Trips $trip) + { + $flights = $trip->flights()->get(); + + return $this->collection($flights, new FlightTransform()); + } +} diff --git a/database/factories/TripsFactory.php b/database/factories/TripsFactory.php new file mode 100644 index 0000000..ae6bf02 --- /dev/null +++ b/database/factories/TripsFactory.php @@ -0,0 +1,24 @@ +define(App\Libraries\Trips\Models\Trips::class, function (Faker\Generator $faker) { + return [ + 'name' => $faker->text(10), + ]; +}); + +$factory->define(App\Libraries\Trips\Models\Flights::class, function (Faker\Generator $faker) { + return [ + 'destination' => $faker->countryISOAlpha3, //TODO change this + ]; +}); diff --git a/database/migrations/.gitkeep b/database/migrations/.gitkeep old mode 100644 new mode 100755 diff --git a/database/migrations/2017_05_14_152748_trips.php b/database/migrations/2017_05_14_152748_trips.php new file mode 100755 index 0000000..dc4de50 --- /dev/null +++ b/database/migrations/2017_05_14_152748_trips.php @@ -0,0 +1,58 @@ +increments('id'); + $table->string('name'); + $table->timestamps(); + }); + + Schema::create('flights', function (Blueprint $table) { + $table->increments('id'); + $table->string('destination'); + $table->timestamps(); + }); + + Schema::create('trip_flights', function (Blueprint $table) { + $table->increments('id'); + $table->integer('trips_id')->unsigned(); + $table->integer('flights_id')->unsigned(); + $table->timestamps(); + + $table->unique(['trips_id', 'flights_id']); + + $table->foreign('trips_id')->references('id')->on('trips'); + }); + + Schema::create('airports', function (Blueprint $table) { + $table->increments('id'); + $table->string('name', 256); + $table->string('code', 3); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::drop('trip_flights'); + Schema::drop('trips'); + Schema::drop('flights'); + Schema::drop('airports'); + } +} diff --git a/database/seeds/DatabaseSeeder.php b/database/seeds/DatabaseSeeder.php old mode 100644 new mode 100755 index 23526c9..61e1db5 --- a/database/seeds/DatabaseSeeder.php +++ b/database/seeds/DatabaseSeeder.php @@ -12,5 +12,16 @@ class DatabaseSeeder extends Seeder public function run() { // $this->call('UsersTableSeeder'); + + factory(App\Libraries\Trips\Models\Trips::class, 5) + ->create() + ->each(function ($trip) { + $flights = factory(App\Libraries\Trips\Models\Flights::class, 2) + ->create() + ->each(function ($flight) use ($trip) { + $trip->flights()->attach($flight->id); + }); + + }); } } diff --git a/database/seeds/TripsSeeder.php b/database/seeds/TripsSeeder.php new file mode 100755 index 0000000..07a4227 --- /dev/null +++ b/database/seeds/TripsSeeder.php @@ -0,0 +1,21 @@ +create() + ->each(function ($trip) { + $trip->flights->save(factory(App\Libraries\Trips\Models\Flights::class, 2)->make()); + }); + } +} diff --git a/routes/web.php b/routes/web.php index 8fa9db5..9301191 100644 --- a/routes/web.php +++ b/routes/web.php @@ -17,3 +17,13 @@ $app->get('/', function () use ($app) { $app->get('/airports', 'AirportController@resourceList'); $app->get('/airports/{code}', 'AirportController@getAirport'); + +$app->get('/trips', 'TripController@listTrips'); +$app->get('/trips/{id}', 'TripController@getTrip'); + +$app->get('/trips/{id}/flights', 'TripController@addFlight'); +$app->post('/trips/{id}/flights', 'TripController@addFlight'); + +$app->get('/flights', 'FlightController@listFlights'); +$app->get('/flights/{id}', 'FlightController@getFlight'); +$app->delete('/flights/{id}', 'FlightController@removeFlight'); diff --git a/tests/ExampleTest.php b/tests/ExampleTest.php old mode 100644 new mode 100755 diff --git a/tests/TestCase.php b/tests/TestCase.php old mode 100644 new mode 100755