Skip to content

Commit

Permalink
refactor recipe controller
Browse files Browse the repository at this point in the history
  • Loading branch information
fokosun committed Sep 9, 2023
1 parent d20fff0 commit 3ddbe29
Show file tree
Hide file tree
Showing 6 changed files with 115 additions and 83 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/feature-test.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Feature test
name: Run Feature tests

on:
push:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/static-analysis.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Static analysis
name: Run Static analysis

on:
push:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/unit-test.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Unit test
name: Run Unit tests

on:
push:
Expand Down
81 changes: 48 additions & 33 deletions app/Http/Controllers/RecipeController.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,21 @@

namespace App\Http\Controllers;

use AllowDynamicProperties;
use App\Http\Requests\RecipeStoreRequest;
use App\Models\Recipe;
use App\Services\RecipeService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Log;
use Symfony\Component\HttpFoundation\Response as ResponseAlias;
use Tymon\JWTAuth\Exceptions\JWTException;
use Tymon\JWTAuth\JWT;

/**
* Class UserController
*/
class RecipeController extends Controller
#[AllowDynamicProperties] class RecipeController extends Controller
{
protected RecipeService $service;

Expand All @@ -33,45 +35,59 @@ public function __construct(RecipeService $service)
}

/**
* Get all recipes belonging to a user
*
* @return \Illuminate\Http\JsonResponse
* @return JsonResponse
*/
public function index(): \Illuminate\Http\JsonResponse
public function index()
{
return $this->service->index();
return $this->successResponse(['data' => $this->service->index()]);
}

/**
* @param $recipeId
* @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Model|object
* @return JsonResponse
* @throws \App\Exceptions\CookbookModelNotFoundException
*/
public function show($recipeId)
public function show($recipeId): JsonResponse
{
return $this->service->show($recipeId);
return $this->successResponse(['data' => $this->service->show($recipeId)]);
}

public function addClap(Request $request)
/**
* @param Request $request
* @return JsonResponse
* @throws \App\Exceptions\CookbookModelNotFoundException
* @throws \Illuminate\Validation\ValidationException
*/
public function addClap(Request $request): JsonResponse
{
$this->validate(
$request, [
'recipe_id' => 'required|exists:recipes,id',
]
);

return $this->service->addClap($request->get('recipe_id'));
return ($recipe = $this->service->addClap($request->get('recipe_id'))) ?
$this->successResponse(['updated' => true, 'claps' => $recipe->claps]) :

Check failure on line 70 in app/Http/Controllers/RecipeController.php

View workflow job for this annotation

GitHub Actions / php-cs

Access to an undefined property Illuminate\Database\Eloquent\Model::$claps.
$this->errorResponse(['error' => 'There was an error processing this request. Please try again.']);
}

public function myRecipes(Request $request, JWT $jwtAuth): \Illuminate\Http\JsonResponse
/**
* @param Request $request
* @param JWT $jwtAuth
* @return JsonResponse
* @throws JWTException
*/
public function myRecipes(Request $request, JWT $jwtAuth): JsonResponse
{
if ($jwtAuth->parseToken()->check()) {
return $this->service->index($request->get('user_id'));
return $this->successResponse([
'data' => $this->service->index($request->get('user_id'))
]);
}

return response()->json([
'error', 'You are not authorized to access this resource.'
], 401);
], ResponseAlias::HTTP_UNAUTHORIZED);
}

public function store(RecipeStoreRequest $request, JWT $jwtAuth)
Expand All @@ -80,16 +96,16 @@ public function store(RecipeStoreRequest $request, JWT $jwtAuth)
$jwtAuth->parseToken()->check();
return $this->service->store($request);
} catch (\Exception $exception) {
Log::debug('An error occured while creating this recipe', [
Log::debug('An error occurred while creating this recipe', [
'resource' => self::RECIPE_RESOURCE,
'exception' => $exception
]);

$message = "There was an error processing this request, please try again later.";
$code = Response::HTTP_BAD_REQUEST;
$code = ResponseAlias::HTTP_BAD_REQUEST;

if ($exception->getCode() == 401) {
$code = Response::HTTP_UNAUTHORIZED;
$code = ResponseAlias::HTTP_UNAUTHORIZED;
$message = "You are not authorized to perform this action.";
}

Expand All @@ -101,33 +117,32 @@ public function store(RecipeStoreRequest $request, JWT $jwtAuth)

public function update(Request $request, $recipeId, JWT $jwtAuth)
{
if (
$request->user()->ownRecipe($recipeId)
) {
if (
$jwtAuth->parseToken()->check()
) {
return $this->service->update($request, $recipeId);
if ($jwtAuth->parseToken()->check() && $request->user()->ownRecipe($recipeId)) {
if ($this->service->update($request, $recipeId)) {
return $this->successResponse(['updated' => true]);
}

return $this->errorResponse(['updated' => false]);
}

return response()->json([
'error' => 'You are not authorized to access this resource.'
], 401);
], ResponseAlias::HTTP_UNAUTHORIZED);
}

public function destroy(Request $request, $recipeId, JWT $jwtAuth)
{
if (
$jwtAuth->parseToken()->check() &&
$request->user()->isSuper()
) {
return $this->service->delete($request->user(), $recipeId);
if ($jwtAuth->parseToken()->check() && $request->user()->isSuper()) {
if ($this->service->delete($request->user(), $recipeId)) {
return $this->successResponse(['deleted' => true]);
}

return $this->errorResponse(['deleted' => false]);
}

return response()->json([
'error' => 'You are not authorized to perform this action.'
], Response::HTTP_UNAUTHORIZED);
], ResponseAlias::HTTP_UNAUTHORIZED);
}

public function report(Request $request, JWT $jwtAuth): JsonResponse
Expand Down Expand Up @@ -155,6 +170,6 @@ public function report(Request $request, JWT $jwtAuth): JsonResponse

return response()->json([
'error' => 'You are not authorized to perform this action.'
], Response::HTTP_UNAUTHORIZED);
], ResponseAlias::HTTP_UNAUTHORIZED);
}
}
64 changes: 18 additions & 46 deletions app/Services/RecipeService.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,13 @@
use Carbon\Carbon;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\Routing\ResponseFactory;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use Symfony\Component\HttpFoundation\Response as ResponseAlias;

/**
* Class RecipeService
Expand All @@ -33,46 +36,25 @@ public function __construct()
$this->serviceModel = new Recipe();
}

/**
* @param $user_id
* @return \Illuminate\Http\JsonResponse
*/
public function index($user_id = null): \Illuminate\Http\JsonResponse
public function index($user_id = null): Collection
{
$recipes = Recipe::paginate(100);

$recipes = $recipes->filter(function ($recipe) {
return !$recipe->is_draft;
});

if ($user_id) {
return response()->json(
[
'data' => $recipes->where('user_id', '=', $user_id),
], Response::HTTP_OK
);
}

return response()->json(['data' => $recipes]);
return $user_id ? $recipes->where('user_id', '=', $user_id) : $recipes;

Check failure on line 47 in app/Services/RecipeService.php

View workflow job for this annotation

GitHub Actions / php-cs

Method App\Services\RecipeService::index() should return Illuminate\Database\Eloquent\Collection but returns Illuminate\Support\Collection<mixed, App\Models\Recipe>.
}

/**
* Retrieve one Recipe
*
* @param $id
* @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Model
*
* @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Model|object|null
* @throws CookbookModelNotFoundException
*/
public function show($id)
{
$recipe = $this->get($id);

if (!$recipe) {
throw new CookbookModelNotFoundException();
}

return $recipe;
return $this->get($id) ?: null;
}

/**
Expand Down Expand Up @@ -144,7 +126,7 @@ public function store($request)
/**
* @param Request $request
* @param $id
* @return Application|ResponseFactory|\Illuminate\Foundation\Application|Response|void
* @return bool|int|void
* @throws CookbookModelNotFoundException
* @throws InvalidPayloadException
*/
Expand Down Expand Up @@ -172,51 +154,41 @@ public function update(Request $request, $id)
->getKey();
}

return response(
[
'updated' => $recipe->update($payload),
], Response::HTTP_OK
);
return $recipe->update($payload);
}
}

/**
* @param User $user
* @param $id
* @return Application|ResponseFactory|\Illuminate\Foundation\Application|Response|void
* @return bool|mixed|void|null
* @throws CookbookModelNotFoundException
*/
public function delete(User $user, $id)
{
if ($user->isSuper()) {
$recipe = $this->get($id);

return response(
[
'deleted' => $recipe->delete(),
], Response::HTTP_ACCEPTED
);
return $recipe->delete();
}
}

/**
* @param $recipeId
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\Routing\ResponseFactory|Response
* @return false|\Illuminate\Database\Eloquent\Model
* @throws CookbookModelNotFoundException
*/
public function addClap($recipeId)
{
$recipe = $this->get($recipeId);

$recipe->claps = $recipe->claps + 1;
$recipe->save();

return response(
[
'updated' => true,
'claps' => $recipe->refresh()->claps,
], Response::HTTP_OK
);

if ($recipe->save()) {
return $recipe->refresh();
}

return false;
}

/**
Expand Down
47 changes: 46 additions & 1 deletion tests/Feature/RecipeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
use Symfony\Component\HttpFoundation\Response as ResponseAlias;

class RecipeTest extends \TestCase
{
Expand Down Expand Up @@ -166,6 +167,50 @@ public function it_cannot_clap_for_a_recipe_that_does_not_exist()
]);
}

/**
* @test
*/
public function it_can_show_a_recipe_by_id_or_slug()
{
$user = User::factory()->make([
'email' => '[email protected]',
'password' => (new BcryptHasher)->make('pass123'),
]);
$user->save();

$token = Auth::attempt([
'email' => '[email protected]',
'password' => 'pass123'
]);

$cookbook = Cookbook::factory()->make([
'user_id' => $user->getKey()
]);

$cookbook->save();

$recipe = Recipe::factory()->make([
'cookbook_id' => $cookbook->refresh()->getKey(),
'user_id' => $user->getKey()
]);

$recipe->save();
$recipe = $recipe->refresh();

$searchBy = ['id', 'slug'];

foreach ($searchBy as $key) {
$this->json(
'GET',
'/api/v1/recipes/' . $recipe->$key,
[],
[
'Authorization' => 'Bearer ' . $token
]
)->assertStatus(ResponseAlias::HTTP_OK)->assertJsonStructure(['data']);
}
}

/**
* @test
*/
Expand Down Expand Up @@ -366,7 +411,7 @@ public function only_supers_can_destroy_a_recipe()
[
'Authorization' => 'Bearer ' . $token
]
)->assertStatus(Response::HTTP_ACCEPTED)
)->assertStatus(ResponseAlias::HTTP_OK)
->assertExactJson([
"deleted" => true
]);
Expand Down

0 comments on commit 3ddbe29

Please sign in to comment.