From 99129e3c766e3b87f88462409fbe3891dc21e073 Mon Sep 17 00:00:00 2001 From: "Christopher C. Wells" Date: Fri, 22 Jan 2021 22:02:20 -0800 Subject: [PATCH] Create IngredientAmount class This class will replace FoodAmount when it has proper support for calculating nutrients for FoodAmount and Recipe combinations. --- app/Models/IngredientAmount.php | 98 +++++++++++++++++++ app/Models/JournalEntry.php | 3 +- app/Models/Recipe.php | 8 +- app/Models/Traits/HasIngredients.php | 16 +++ app/Models/Traits/Ingredient.php | 9 ++ ...212856_create_ingredient_amounts_table.php | 39 ++++++++ 6 files changed, 171 insertions(+), 2 deletions(-) create mode 100644 app/Models/IngredientAmount.php create mode 100644 app/Models/Traits/HasIngredients.php create mode 100644 database/migrations/2021_01_22_212856_create_ingredient_amounts_table.php diff --git a/app/Models/IngredientAmount.php b/app/Models/IngredientAmount.php new file mode 100644 index 0000000..4bf80b9 --- /dev/null +++ b/app/Models/IngredientAmount.php @@ -0,0 +1,98 @@ + 'float', + 'weight' => 'int', + ]; + + /** + * @inheritdoc + */ + protected $with = ['ingredient']; + + /** + * Nutrient calculation methods. + */ + private array $nutrientMethods = [ + 'calories', + 'carbohydrates', + 'cholesterol', + 'fat', + 'protein', + 'sodium', + ]; + + /** + * @inheritdoc + */ + protected $appends = ['amount_formatted']; + + /** + * Get the amount as a formatted string (e.g. 0.5 = 1/2). + */ + public function getAmountFormattedAttribute(): string { + return Number::fractionStringFromFloat($this->amount); + } + + /** + * Get the ingredient type (Food or Recipe). + */ + public function ingredient(): BelongsTo { + return $this->morphTo(); + } + + /** + * Get the parent (Recipe or JournalEntry). + */ + public function parent(): BelongsTo { + return $this->morphTo(); + } + + /** + * Add nutrient calculations handling to overloading. + * + * @param string $method + * @param array $parameters + * + * @return mixed + * + * @noinspection PhpMissingParamTypeInspection + */ + public function __call($method, $parameters): mixed { + if (in_array($method, $this->nutrientMethods)) { + return $this->ingredient->{$method} * Nutrients::calculateFoodNutrientMultiplier( + $this->ingredient, + $this->amount, + $this->unit + ); + } + else { + return parent::__call($method, $parameters); + } + } +} diff --git a/app/Models/JournalEntry.php b/app/Models/JournalEntry.php index c1c0649..090d50a 100644 --- a/app/Models/JournalEntry.php +++ b/app/Models/JournalEntry.php @@ -2,6 +2,7 @@ namespace App\Models; +use App\Models\Traits\HasIngredients; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; @@ -48,7 +49,7 @@ use Illuminate\Database\Eloquent\Relations\MorphToMany; */ class JournalEntry extends Model { - use HasFactory; + use HasFactory, HasIngredients; /** * @inheritdoc diff --git a/app/Models/Recipe.php b/app/Models/Recipe.php index 856a910..c7906af 100644 --- a/app/Models/Recipe.php +++ b/app/Models/Recipe.php @@ -2,6 +2,7 @@ namespace App\Models; +use App\Models\Traits\HasIngredients; use App\Models\Traits\Ingredient; use App\Models\Traits\Journalable; use App\Models\Traits\Sluggable; @@ -42,7 +43,7 @@ use Illuminate\Database\Eloquent\Relations\HasMany; */ class Recipe extends Model { - use HasFactory, Ingredient, Journalable, Sluggable; + use HasFactory, HasIngredients, Ingredient, Journalable, Sluggable; /** * @inheritdoc @@ -85,6 +86,11 @@ class Recipe extends Model 'sodiumPerServing', ]; + /** + * @inheritdoc + */ + protected $with = ['ingredients']; + /** * Get the steps for this Recipe. */ diff --git a/app/Models/Traits/HasIngredients.php b/app/Models/Traits/HasIngredients.php new file mode 100644 index 0000000..58643c5 --- /dev/null +++ b/app/Models/Traits/HasIngredients.php @@ -0,0 +1,16 @@ +morphMany(IngredientAmount::class, 'parent'); + } +} diff --git a/app/Models/Traits/Ingredient.php b/app/Models/Traits/Ingredient.php index d27ebb3..0e9ab0e 100644 --- a/app/Models/Traits/Ingredient.php +++ b/app/Models/Traits/Ingredient.php @@ -2,10 +2,19 @@ namespace App\Models\Traits; +use App\Models\IngredientAmount; +use Illuminate\Database\Eloquent\Relations\MorphToMany; use Illuminate\Support\Collection; trait Ingredient { + /** + * Get all of the ingredient amounts for this ingredient. + */ + public function ingredientAmounts(): MorphToMany { + return $this->morphToMany(IngredientAmount::class, 'ingredient'); + } + /** * Gets search results for a term. */ diff --git a/database/migrations/2021_01_22_212856_create_ingredient_amounts_table.php b/database/migrations/2021_01_22_212856_create_ingredient_amounts_table.php new file mode 100644 index 0000000..c994f32 --- /dev/null +++ b/database/migrations/2021_01_22_212856_create_ingredient_amounts_table.php @@ -0,0 +1,39 @@ +id(); + $table->unsignedInteger('ingredient_id'); + $table->string('ingredient_type'); + $table->unsignedFloat('amount'); + $table->enum('unit', ['tsp', 'tbsp', 'cup', 'oz', 'gram', 'serving'])->nullable(); + $table->string('detail')->nullable(); + $table->unsignedInteger('weight'); + $table->unsignedInteger('parent_id'); + $table->string('parent_type'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('ingredient_amounts'); + } +}