From 4aaf83c862152264078026258a71e4e30be197dd Mon Sep 17 00:00:00 2001 From: "Christopher C. Wells" Date: Sun, 6 Mar 2022 20:14:36 -0800 Subject: [PATCH] Add recipe duplicate functionality --- app/Http/Controllers/RecipeController.php | 25 ++++++++++ app/Models/Recipe.php | 52 +++++++++++++++++++++ resources/views/recipes/duplicate.blade.php | 30 ++++++++++++ resources/views/recipes/show.blade.php | 3 ++ routes/auth.php | 3 ++ 5 files changed, 113 insertions(+) create mode 100644 resources/views/recipes/duplicate.blade.php diff --git a/app/Http/Controllers/RecipeController.php b/app/Http/Controllers/RecipeController.php index af0b77b..fad38fe 100644 --- a/app/Http/Controllers/RecipeController.php +++ b/app/Http/Controllers/RecipeController.php @@ -12,6 +12,7 @@ use App\Support\Number; use App\Support\Nutrients; use Illuminate\Contracts\View\View; use Illuminate\Http\RedirectResponse; +use Illuminate\Http\Request; use Illuminate\Support\Collection; use Illuminate\Support\Facades\DB; use Illuminate\Support\Str; @@ -350,6 +351,30 @@ class RecipeController extends Controller $recipe->ingredientSeparators()->saveMany($ingredient_separators); } + /** + * Confirm duplicating recipe. + */ + public function duplicateConfirm(Recipe $recipe): View { + return view('recipes.duplicate')->with('recipe', $recipe); + } + + /** + * Duplicate a recipe. + */ + public function duplicate(Request $request, Recipe $recipe): RedirectResponse + { + $attributes = $request->validate(['name' => ['required', 'string']]); + + try { + $new_recipe = $recipe->duplicate($attributes); + } catch (\Throwable $e) { + return back()->withInput()->withErrors($e->getMessage()); + } + + return redirect()->route('recipes.show', $new_recipe) + ->with('message', "Recipe {$recipe->name} duplicated!"); + } + /** * Confirm removal of specified resource. */ diff --git a/app/Models/Recipe.php b/app/Models/Recipe.php index e4d5600..d8a15bd 100644 --- a/app/Models/Recipe.php +++ b/app/Models/Recipe.php @@ -14,6 +14,7 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Support\Collection; +use Illuminate\Support\Facades\DB; use Spatie\Image\Manipulations; use Spatie\MediaLibrary\HasMedia; use Spatie\MediaLibrary\InteractsWithMedia; @@ -262,4 +263,55 @@ final class Recipe extends Model implements HasMedia ->optimize(); } + /** + * Duplicates the recipe, updating provided attributes. + * + * @throws \Throwable + */ + public function duplicate(array $attributes): Recipe { + /** @var \App\Models\Recipe $recipe */ + $recipe = $this->replicate(); + $recipe->fill($attributes); + + try { + DB::transaction(function () use ($recipe) { + $recipe->save(); + + $recipe->tags()->attach($this->tags); + + $ingredient_amounts = []; + foreach ($this->ingredientAmounts as $ia) { + $new_ia = $ia->replicate(); + $new_ia->parent_id = $recipe->id; + $new_ia->parent_type = Recipe::class; + $ingredient_amounts[] = $new_ia; + } + $recipe->ingredientAmounts()->saveMany($ingredient_amounts); + + $steps = []; + foreach ($this->steps as $step) { + $new_step = $step->replicate(); + $new_step->recipe_id = $recipe->id; + $steps[] = $new_step; + } + $recipe->steps()->saveMany($steps); + + $separators = []; + foreach ($this->separators as $separator) { + $new_separator = $separator->replicate(); + $new_separator->recipe_id = $recipe->id; + $separators[] = $new_separator; + } + $recipe->separators()->saveMany($separators); + + $recipe->push(); + }); + } catch (\Throwable $e) { + DB::rollBack(); + throw $e; + } + + return $recipe; + } + } diff --git a/resources/views/recipes/duplicate.blade.php b/resources/views/recipes/duplicate.blade.php new file mode 100644 index 0000000..f891804 --- /dev/null +++ b/resources/views/recipes/duplicate.blade.php @@ -0,0 +1,30 @@ + + Duplicate {{ $recipe->name }} + +

+ Duplicate {{ $recipe->name }}? +

+
+
+ @csrf +
+ +
+ + + +
+
+
+ + Duplicate + + + Cancel +
+
+
diff --git a/resources/views/recipes/show.blade.php b/resources/views/recipes/show.blade.php index 6642ca7..ddfe6c7 100644 --- a/resources/views/recipes/show.blade.php +++ b/resources/views/recipes/show.blade.php @@ -167,6 +167,9 @@ Edit Recipe + + Duplicate Recipe + Delete Recipe diff --git a/routes/auth.php b/routes/auth.php index 3ad7c89..5e4f7c9 100644 --- a/routes/auth.php +++ b/routes/auth.php @@ -49,6 +49,9 @@ Route::middleware(['auth'])->group(function () { // Recipes. Route::resource('recipes', RecipeController::class); Route::get('/recipes/{recipe}/delete', [RecipeController::class, 'delete'])->name('recipes.delete'); + Route::get('/recipes/{recipe}/duplicate', [RecipeController::class, 'duplicateConfirm'])->name('recipes.duplicate.confirm'); + Route::post('/recipes/{recipe}/duplicate', [RecipeController::class, 'duplicate'])->name('recipes.duplicate'); + // Users. Route::get('/profile/{user}', [ProfileController::class, 'show'])->name('profiles.show');