diff --git a/app/Http/Controllers/RecipeController.php b/app/Http/Controllers/RecipeController.php index 9941423..7572e77 100644 --- a/app/Http/Controllers/RecipeController.php +++ b/app/Http/Controllers/RecipeController.php @@ -2,9 +2,9 @@ namespace App\Http\Controllers; -use App\Models\Food; use App\Models\IngredientAmount; use App\Models\Recipe; +use App\Models\RecipeSeparator; use App\Models\RecipeStep; use App\Rules\ArrayNotEmpty; use App\Rules\StringIsDecimalOrFraction; @@ -186,6 +186,12 @@ class RecipeController extends Controller 'ingredients.key.*' => ['nullable', 'int'], 'ingredients.weight' => ['required', 'array', new ArrayNotEmpty], 'ingredients.weight.*' => ['required', 'int'], + 'separators.key' => ['nullable', 'array'], + 'separators.key.*' => ['nullable', 'int'], + 'separators.weight' => ['nullable', 'array'], + 'separators.weight.*' => ['required', 'int'], + 'separators.text' => ['nullable', 'array'], + 'separators.text.*' => ['nullable', 'string'], 'steps.step' => ['required', 'array', new ArrayNotEmpty], 'steps.step.*' => ['nullable', 'string'], 'steps.key' => ['nullable', 'array'], @@ -213,52 +219,11 @@ class RecipeController extends Controller try { DB::transaction(function () use ($recipe, $input) { $recipe->saveOrFail(); - - // Delete any removed ingredients. - $removed = array_diff($recipe->ingredientAmounts->keys()->all(), $input['ingredients']['key']); - foreach ($removed as $removed_key) { - $recipe->ingredientAmounts[$removed_key]->delete(); + $this->updateIngredients($recipe, $input); + if (isset($input['separators'])) { + $this->updateIngredientSeparators($recipe, $input); } - - // Add/update current ingredients. - $ingredient_amounts = []; - foreach (array_filter($input['ingredients']['id']) as $key => $ingredient_id) { - if (!is_null($input['ingredients']['key'][$key])) { - $ingredient_amounts[$key] = $recipe->ingredientAmounts[$input['ingredients']['key'][$key]]; - } - else { - $ingredient_amounts[$key] = new IngredientAmount(); - } - $ingredient_amounts[$key]->fill([ - 'amount' => Number::floatFromString($input['ingredients']['amount'][$key]), - 'unit' => $input['ingredients']['unit'][$key], - 'detail' => $input['ingredients']['detail'][$key], - 'weight' => (int) $input['ingredients']['weight'][$key], - ]); - $ingredient_amounts[$key]->ingredient() - ->associate($input['ingredients']['type'][$key]::where('id', $ingredient_id)->first()); - } - $recipe->ingredientAmounts()->saveMany($ingredient_amounts); - - $steps = []; - $number = 1; - - // Delete any removed steps. - $removed = array_diff($recipe->steps->keys()->all(), $input['steps']['key']); - foreach ($removed as $removed_key) { - $recipe->steps[$removed_key]->delete(); - } - - foreach (array_filter($input['steps']['step']) as $key => $step) { - if (!is_null($input['steps']['key'][$key])) { - $steps[$key] = $recipe->steps[$input['steps']['key'][$key]]; - } - else { - $steps[$key] = new RecipeStep(); - } - $steps[$key]->fill(['number' => $number++, 'step' => $step]); - } - $recipe->steps()->saveMany($steps); + $this->updateSteps($recipe, $input); }); } catch (\Exception $e) { DB::rollBack(); @@ -293,6 +258,106 @@ class RecipeController extends Controller return redirect()->route('recipes.show', $recipe); } + /** + * Updates recipe ingredients data based on input. + * + * @param \App\Models\Recipe $recipe + * @param array $input + * + * @throws \Exception + */ + private function updateIngredients(Recipe $recipe, array $input): void { + // Delete any removed ingredients. + $removed = array_diff($recipe->ingredientAmounts->keys()->all(), $input['ingredients']['key']); + foreach ($removed as $removed_key) { + $recipe->ingredientAmounts[$removed_key]->delete(); + } + + // Add/update current ingredients. + $ingredient_amounts = []; + foreach (array_filter($input['ingredients']['id']) as $key => $ingredient_id) { + if (!is_null($input['ingredients']['key'][$key])) { + $ingredient_amounts[$key] = $recipe->ingredientAmounts[$input['ingredients']['key'][$key]]; + } + else { + $ingredient_amounts[$key] = new IngredientAmount(); + } + $ingredient_amounts[$key]->fill([ + 'amount' => Number::floatFromString($input['ingredients']['amount'][$key]), + 'unit' => $input['ingredients']['unit'][$key], + 'detail' => $input['ingredients']['detail'][$key], + 'weight' => (int) $input['ingredients']['weight'][$key], + ]); + $ingredient_amounts[$key]->ingredient() + ->associate($input['ingredients']['type'][$key]::where('id', $ingredient_id)->first()); + } + $recipe->ingredientAmounts()->saveMany($ingredient_amounts); + } + + /** + * Updates recipe steps data based on input. + * + * @param \App\Models\Recipe $recipe + * @param array $input + * + * @throws \Exception + */ + private function updateSteps(Recipe $recipe, array $input): void { + $steps = []; + $number = 1; + + // Delete any removed steps. + $removed = array_diff($recipe->steps->keys()->all(), $input['steps']['key']); + foreach ($removed as $removed_key) { + $recipe->steps[$removed_key]->delete(); + } + + foreach (array_filter($input['steps']['step']) as $key => $step) { + if (!is_null($input['steps']['key'][$key])) { + $steps[$key] = $recipe->steps[$input['steps']['key'][$key]]; + } + else { + $steps[$key] = new RecipeStep(); + } + $steps[$key]->fill(['number' => $number++, 'step' => $step]); + } + $recipe->steps()->saveMany($steps); + } + + /** + * Updates recipe ingredient separators data based on input. + * + * @param \App\Models\Recipe $recipe + * @param array $input + * + * @throws \Exception + */ + private function updateIngredientSeparators(Recipe $recipe, array $input): void { + // Delete any removed separators. + $removed = array_diff($recipe->ingredientSeparators->keys()->all(), $input['separators']['key']); + foreach ($removed as $removed_key) { + $recipe->ingredientSeparators[$removed_key]->delete(); + } + + // Add/update current ingredients. + $ingredient_separators = []; + foreach ($input['separators']['key'] as $index => $key) { + if (!is_null($key)) { + $ingredient_separators[$index] = $recipe->ingredientSeparators[$key]; + } + else { + $ingredient_separators[$index] = new RecipeSeparator(); + } + $ingredient_separators[$index]->fill([ + 'container' => 'ingredients', + 'text' => $input['separators']['text'][$index], + 'weight' => (int) $input['separators']['weight'][$index], + ]); + + } + $recipe->ingredientSeparators()->saveMany($ingredient_separators); + } + /** * Confirm removal of specified resource. */ diff --git a/app/Models/RecipeSeparator.php b/app/Models/RecipeSeparator.php index a5efbc9..f4ea5bd 100644 --- a/app/Models/RecipeSeparator.php +++ b/app/Models/RecipeSeparator.php @@ -28,7 +28,7 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo; * @method static \Illuminate\Database\Eloquent\Builder|RecipeSeparator whereWeight($value) * @mixin \Eloquent */ -class RecipeSeparator extends Model +final class RecipeSeparator extends Model { /** * @inheritdoc diff --git a/app/Support/ArrayFormat.php b/app/Support/ArrayFormat.php index b33a2da..b47dbc5 100644 --- a/app/Support/ArrayFormat.php +++ b/app/Support/ArrayFormat.php @@ -42,6 +42,8 @@ class ArrayFormat * * @return array * The flipped array. + * + * @todo Return Collection instead of array. */ public static function flipTwoDimensionalKeys(array $array): array { $flipped = []; diff --git a/database/migrations/2021_03_26_052715_create_recipe_separators_table.php b/database/migrations/2021_03_26_052715_create_recipe_separators_table.php index 6f0a7cc..f24c5cb 100644 --- a/database/migrations/2021_03_26_052715_create_recipe_separators_table.php +++ b/database/migrations/2021_03_26_052715_create_recipe_separators_table.php @@ -19,7 +19,7 @@ class CreateRecipeSeparatorsTable extends Migration $table->foreignIdFor(Recipe::class)->index()->constrained()->cascadeOnUpdate()->cascadeOnDelete(); $table->string('container')->index(); $table->unsignedInteger('weight')->index(); - $table->longText('text'); + $table->longText('text')->nullable(); $table->timestamps(); }); }