added imlementation of API,

updated AGENTS.md by Codex
This commit is contained in:
2026-02-12 01:36:37 +01:00
parent 6b718a3cfa
commit 5b93cdd002
2 changed files with 894 additions and 9 deletions

View File

@ -5,7 +5,843 @@ namespace TPsoft\Nutrio;
require_once __DIR__.'/Init.php';
use TPsoft\APIlite\APIlite;
use TPsoft\Nutrio\Models\DiaryDays;
use TPsoft\Nutrio\Models\DiaryEntries;
use TPsoft\Nutrio\Models\Ingredients;
use TPsoft\Nutrio\Models\MealItems;
use TPsoft\Nutrio\Models\Meals;
use TPsoft\Nutrio\Models\Options;
use TPsoft\Nutrio\Models\Users;
class API extends APIlite {
private ?Users $usersModel = null;
private ?Ingredients $ingredientsModel = null;
private ?Meals $mealsModel = null;
private ?MealItems $mealItemsModel = null;
private ?DiaryDays $diaryDaysModel = null;
private ?DiaryEntries $diaryEntriesModel = null;
private ?Options $optionsModel = null;
public function health(): array
{
$dbVersion = null;
$versionRow = $this->options()->option('version');
if (is_array($versionRow) && isset($versionRow['value'])) {
$dbVersion = (string) $versionRow['value'];
}
return array(
'service' => 'Nutrio API',
'timestamp' => date('c'),
'db_type' => $this->users()->getDBtype(),
'db_version' => $dbVersion
);
}
public function ingredientList(int $user_id, string $query = '', bool $include_global = true): array
{
$this->assertUserExists($user_id);
$search = array(
'user_id' => $include_global ? array($user_id, null) : $user_id
);
$query = trim($query);
if (strlen($query) > 0) {
$search['name'] = '%' . $query . '%';
}
$list = $this->ingredients()->getList($search);
$list = is_array($list) ? $list : array();
$result = array();
foreach ($list as $row) {
$result[] = $this->mapIngredient($row);
}
return $result;
}
public function ingredientGet(int $user_id, int $ingredient_id): array
{
$this->assertUserExists($user_id);
return $this->mapIngredient($this->getIngredientAccessible($user_id, $ingredient_id));
}
public function ingredientCreate(
int $user_id,
string $name,
float $protein_g_100,
float $carbs_g_100,
float $sugar_g_100,
float $fat_g_100,
float $fiber_g_100 = 0,
float $kcal_100 = 0
): array {
$this->assertUserExists($user_id);
$name = $this->normalizeName($name);
$this->assertNonNegative('protein_g_100', $protein_g_100);
$this->assertNonNegative('carbs_g_100', $carbs_g_100);
$this->assertNonNegative('sugar_g_100', $sugar_g_100);
$this->assertNonNegative('fat_g_100', $fat_g_100);
$this->assertNonNegative('fiber_g_100', $fiber_g_100);
if ($kcal_100 < 0) {
throw new \Exception('kcal_100 cannot be negative');
}
if ($kcal_100 == 0) {
$kcal_100 = $this->computeKcal100($protein_g_100, $carbs_g_100, $fat_g_100);
}
$ingredientId = $this->ingredients()->ingredientSave(array(
'user_id' => $user_id,
'name' => $name,
'protein_g_100' => $this->round2($protein_g_100),
'carbs_g_100' => $this->round2($carbs_g_100),
'sugar_g_100' => $this->round2($sugar_g_100),
'fat_g_100' => $this->round2($fat_g_100),
'fiber_g_100' => $this->round2($fiber_g_100),
'kcal_100' => $this->round2($kcal_100),
'created_at' => '`NOW`'
));
if ($ingredientId === false) {
throw new \Exception('Failed to create ingredient');
}
$created = $this->ingredients()->ingredient((int) $ingredientId);
if (!is_array($created)) {
throw new \Exception('Failed to load created ingredient');
}
return $this->mapIngredient($created);
}
public function ingredientUpdate(
int $user_id,
int $ingredient_id,
string $name,
float $protein_g_100,
float $carbs_g_100,
float $sugar_g_100,
float $fat_g_100,
float $fiber_g_100 = 0,
float $kcal_100 = 0
): array {
$this->assertUserExists($user_id);
$this->getIngredientOwned($user_id, $ingredient_id);
$name = $this->normalizeName($name);
$this->assertNonNegative('protein_g_100', $protein_g_100);
$this->assertNonNegative('carbs_g_100', $carbs_g_100);
$this->assertNonNegative('sugar_g_100', $sugar_g_100);
$this->assertNonNegative('fat_g_100', $fat_g_100);
$this->assertNonNegative('fiber_g_100', $fiber_g_100);
if ($kcal_100 < 0) {
throw new \Exception('kcal_100 cannot be negative');
}
if ($kcal_100 == 0) {
$kcal_100 = $this->computeKcal100($protein_g_100, $carbs_g_100, $fat_g_100);
}
$updated = $this->ingredients()->ingredient($ingredient_id, array(
'name' => $name,
'protein_g_100' => $this->round2($protein_g_100),
'carbs_g_100' => $this->round2($carbs_g_100),
'sugar_g_100' => $this->round2($sugar_g_100),
'fat_g_100' => $this->round2($fat_g_100),
'fiber_g_100' => $this->round2($fiber_g_100),
'kcal_100' => $this->round2($kcal_100)
));
if ($updated === false) {
throw new \Exception('Failed to update ingredient');
}
$row = $this->ingredients()->ingredient($ingredient_id);
if (!is_array($row)) {
throw new \Exception('Failed to load updated ingredient');
}
return $this->mapIngredient($row);
}
public function ingredientDelete(int $user_id, int $ingredient_id): array
{
$this->assertUserExists($user_id);
$this->getIngredientOwned($user_id, $ingredient_id);
$deleted = $this->ingredients()->ingredient($ingredient_id, null);
if ($deleted === false) {
throw new \Exception('Failed to delete ingredient');
}
return array(
'deleted' => true,
'ingredient_id' => $ingredient_id
);
}
public function mealList(int $user_id, string $meal_type = '', bool $with_items = false, bool $with_totals = false): array
{
$this->assertUserExists($user_id);
$search = array('user_id' => $user_id);
$meal_type = trim($meal_type);
if (strlen($meal_type) > 0) {
$this->assertMealType($meal_type);
$search['meal_type'] = $meal_type;
}
$rows = $this->meals()->getList($search);
$rows = is_array($rows) ? $rows : array();
$result = array();
foreach ($rows as $row) {
$meal = $this->mapMeal($row);
$calculatedItems = null;
if ($with_items) {
$calculatedItems = $this->buildMealItems((int) $meal['meal_id'], true);
$meal['items'] = $calculatedItems;
}
if ($with_totals) {
if (is_array($calculatedItems)) {
$meal['totals'] = $this->totalsFromCalculatedItems($calculatedItems);
} else {
$meal['totals'] = $this->calculateMealTotals((int) $meal['meal_id']);
}
}
$result[] = $meal;
}
return $result;
}
public function mealGet(int $user_id, int $meal_id, bool $with_items = true, bool $with_totals = true): array
{
$this->assertUserExists($user_id);
$meal = $this->mapMeal($this->getMealOwned($user_id, $meal_id));
$calculatedItems = null;
if ($with_items) {
$calculatedItems = $this->buildMealItems($meal_id, true);
$meal['items'] = $calculatedItems;
}
if ($with_totals) {
if (is_array($calculatedItems)) {
$meal['totals'] = $this->totalsFromCalculatedItems($calculatedItems);
} else {
$meal['totals'] = $this->calculateMealTotals($meal_id);
}
}
return $meal;
}
public function mealCreate(int $user_id, string $name, string $meal_type): array
{
$this->assertUserExists($user_id);
$name = $this->normalizeName($name);
$this->assertMealType($meal_type);
$mealId = $this->meals()->mealSave(array(
'user_id' => $user_id,
'name' => $name,
'meal_type' => $meal_type,
'created_at' => '`NOW`'
));
if ($mealId === false) {
throw new \Exception('Failed to create meal');
}
return $this->mealGet($user_id, (int) $mealId, false, false);
}
public function mealUpdate(int $user_id, int $meal_id, string $name, string $meal_type): array
{
$this->assertUserExists($user_id);
$this->getMealOwned($user_id, $meal_id);
$name = $this->normalizeName($name);
$this->assertMealType($meal_type);
$updated = $this->meals()->meal($meal_id, array(
'name' => $name,
'meal_type' => $meal_type
));
if ($updated === false) {
throw new \Exception('Failed to update meal');
}
return $this->mealGet($user_id, $meal_id, false, false);
}
public function mealDelete(int $user_id, int $meal_id): array
{
$this->assertUserExists($user_id);
$this->getMealOwned($user_id, $meal_id);
$deleted = $this->meals()->meal($meal_id, null);
if ($deleted === false) {
throw new \Exception('Failed to delete meal');
}
return array(
'deleted' => true,
'meal_id' => $meal_id
);
}
public function mealItemList(int $user_id, int $meal_id, bool $with_calculated = true): array
{
$this->assertUserExists($user_id);
$this->getMealOwned($user_id, $meal_id);
return array(
'meal_id' => $meal_id,
'items' => $this->buildMealItems($meal_id, $with_calculated)
);
}
public function mealItemAdd(int $user_id, int $meal_id, int $ingredient_id, float $grams, int $position = 1): array
{
$this->assertUserExists($user_id);
$this->getMealOwned($user_id, $meal_id);
$this->assertPositive('grams', $grams);
if ($position < 1) {
throw new \Exception('position must be >= 1');
}
$this->getIngredientAccessible($user_id, $ingredient_id);
$mealItemId = $this->mealItems()->mealItemSave(array(
'meal_id' => $meal_id,
'ingredient_id' => $ingredient_id,
'grams' => $this->round2($grams),
'position' => $position
));
if ($mealItemId === false) {
throw new \Exception('Failed to add meal item');
}
$item = $this->getMealItemOwned($user_id, (int) $mealItemId);
return $this->enrichMealItem($item);
}
public function mealItemUpdate(int $user_id, int $meal_item_id, int $ingredient_id, float $grams, int $position): array
{
$this->assertUserExists($user_id);
$item = $this->getMealItemOwned($user_id, $meal_item_id);
$this->assertPositive('grams', $grams);
if ($position < 1) {
throw new \Exception('position must be >= 1');
}
$this->getIngredientAccessible($user_id, $ingredient_id);
$updated = $this->mealItems()->mealItem($meal_item_id, array(
'ingredient_id' => $ingredient_id,
'grams' => $this->round2($grams),
'position' => $position
));
if ($updated === false) {
throw new \Exception('Failed to update meal item');
}
$item = $this->getMealItemOwned($user_id, (int) $item['meal_item_id']);
return $this->enrichMealItem($item);
}
public function mealItemDelete(int $user_id, int $meal_item_id): array
{
$this->assertUserExists($user_id);
$item = $this->getMealItemOwned($user_id, $meal_item_id);
$deleted = $this->mealItems()->mealItem($meal_item_id, null);
if ($deleted === false) {
throw new \Exception('Failed to delete meal item');
}
return array(
'deleted' => true,
'meal_item_id' => $meal_item_id,
'meal_id' => (int) $item['meal_id']
);
}
public function mealItemReorder(int $user_id, int $meal_id, array $ordered_item_ids): array
{
$this->assertUserExists($user_id);
$this->getMealOwned($user_id, $meal_id);
if (count($ordered_item_ids) <= 0) {
throw new \Exception('ordered_item_ids cannot be empty');
}
$currentItems = $this->buildMealItems($meal_id, false);
$currentIds = array();
foreach ($currentItems as $item) {
$currentIds[] = (int) $item['meal_item_id'];
}
$orderedIds = array_values(array_map('intval', $ordered_item_ids));
sort($currentIds);
$checkIds = $orderedIds;
sort($checkIds);
if ($currentIds !== $checkIds) {
throw new \Exception('ordered_item_ids must match all meal item ids exactly');
}
foreach ($orderedIds as $index => $mealItemId) {
$ok = $this->mealItems()->mealItem($mealItemId, array('position' => $index + 1));
if ($ok === false) {
throw new \Exception('Failed to reorder meal items');
}
}
return array(
'meal_id' => $meal_id,
'items' => $this->buildMealItems($meal_id, true)
);
}
public function mealTotals(int $user_id, int $meal_id): array
{
$this->assertUserExists($user_id);
$this->getMealOwned($user_id, $meal_id);
return array(
'meal_id' => $meal_id,
'totals' => $this->calculateMealTotals($meal_id)
);
}
public function diaryDayGet(int $user_id, string $day_date, bool $with_totals = true): array
{
$this->assertUserExists($user_id);
$this->assertDate($day_date);
return $this->buildDiaryDay($user_id, $day_date, $with_totals);
}
public function diaryDaySetMeal(int $user_id, string $day_date, string $meal_type, int $meal_id): array
{
$this->assertUserExists($user_id);
$this->assertDate($day_date);
$this->assertMealType($meal_type);
$meal = $this->getMealOwned($user_id, $meal_id);
if ($meal['meal_type'] !== $meal_type) {
throw new \Exception('meal_type does not match selected meal');
}
$day = $this->ensureDiaryDay($user_id, $day_date);
$existing = $this->diaryEntries()->search('diaryEntries')
->where(array(
'diary_day_id' => (int) $day['diary_day_id'],
'meal_type' => $meal_type
))
->toArrayFirst();
if (is_array($existing) && isset($existing['diary_entry_id'])) {
$updated = $this->diaryEntries()->diaryEntry((int) $existing['diary_entry_id'], array(
'meal_id' => $meal_id
));
if ($updated === false) {
throw new \Exception('Failed to update diary entry');
}
} else {
$inserted = $this->diaryEntries()->diaryEntrySave(array(
'diary_day_id' => (int) $day['diary_day_id'],
'meal_type' => $meal_type,
'meal_id' => $meal_id,
'created_at' => '`NOW`'
));
if ($inserted === false) {
throw new \Exception('Failed to create diary entry');
}
}
return $this->buildDiaryDay($user_id, $day_date, true);
}
public function diaryDayUnsetMeal(int $user_id, string $day_date, string $meal_type): array
{
$this->assertUserExists($user_id);
$this->assertDate($day_date);
$this->assertMealType($meal_type);
$day = $this->getDiaryDay($user_id, $day_date);
if ($day === false) {
return $this->buildDiaryDay($user_id, $day_date, true);
}
$existing = $this->diaryEntries()->search('diaryEntries')
->where(array(
'diary_day_id' => (int) $day['diary_day_id'],
'meal_type' => $meal_type
))
->toArrayFirst();
if (is_array($existing) && isset($existing['diary_entry_id'])) {
$deleted = $this->diaryEntries()->diaryEntry((int) $existing['diary_entry_id'], null);
if ($deleted === false) {
throw new \Exception('Failed to delete diary entry');
}
}
return $this->buildDiaryDay($user_id, $day_date, true);
}
public function diaryRange(int $user_id, string $date_from, string $date_to): array
{
$this->assertUserExists($user_id);
$this->assertDate($date_from);
$this->assertDate($date_to);
if ($date_from > $date_to) {
throw new \Exception('date_from must be before or equal to date_to');
}
$rows = $this->diaryDays()->search('diaryDays')
->where(array('user_id' => $user_id))
->where(array('day_date' => '>=' . $date_from))
->where(array('day_date' => '<=' . $date_to))
->order(array('day_date' => 'ASC'))
->toArray();
$rows = is_array($rows) ? $rows : array();
$days = array();
$totals = $this->emptyTotals();
foreach ($rows as $row) {
$day = $this->buildDiaryDay($user_id, (string) $row['day_date'], true);
$days[] = $day;
if (isset($day['totals']) && is_array($day['totals'])) {
$totals = $this->addTotals($totals, $day['totals']);
}
}
return array(
'user_id' => $user_id,
'date_from' => $date_from,
'date_to' => $date_to,
'days' => $days,
'totals' => $totals
);
}
private function users(): Users
{
if ($this->usersModel === null) {
$this->usersModel = new Users();
}
return $this->usersModel;
}
private function ingredients(): Ingredients
{
if ($this->ingredientsModel === null) {
$this->ingredientsModel = new Ingredients();
}
return $this->ingredientsModel;
}
private function meals(): Meals
{
if ($this->mealsModel === null) {
$this->mealsModel = new Meals();
}
return $this->mealsModel;
}
private function mealItems(): MealItems
{
if ($this->mealItemsModel === null) {
$this->mealItemsModel = new MealItems();
}
return $this->mealItemsModel;
}
private function diaryDays(): DiaryDays
{
if ($this->diaryDaysModel === null) {
$this->diaryDaysModel = new DiaryDays();
}
return $this->diaryDaysModel;
}
private function diaryEntries(): DiaryEntries
{
if ($this->diaryEntriesModel === null) {
$this->diaryEntriesModel = new DiaryEntries();
}
return $this->diaryEntriesModel;
}
private function options(): Options
{
if ($this->optionsModel === null) {
$this->optionsModel = new Options();
}
return $this->optionsModel;
}
private function assertUserExists(int $user_id): void
{
if ($user_id <= 0) {
throw new \Exception('user_id must be > 0');
}
if (!$this->users()->exist($user_id)) {
throw new \Exception('User not found');
}
}
private function assertMealType(string $meal_type): void
{
$allowed = array('breakfast', 'lunch', 'dinner');
if (!in_array($meal_type, $allowed, true)) {
throw new \Exception('Invalid meal_type');
}
}
private function assertDate(string $day_date): void
{
$dt = \DateTime::createFromFormat('Y-m-d', $day_date);
if (!$dt || $dt->format('Y-m-d') !== $day_date) {
throw new \Exception('Invalid date format, expected YYYY-MM-DD');
}
}
private function assertNonNegative(string $name, float $value): void
{
if ($value < 0) {
throw new \Exception($name . ' cannot be negative');
}
}
private function assertPositive(string $name, float $value): void
{
if ($value <= 0) {
throw new \Exception($name . ' must be > 0');
}
}
private function normalizeName(string $name): string
{
$name = trim($name);
if (strlen($name) <= 0) {
throw new \Exception('name is required');
}
if (strlen($name) > 255) {
throw new \Exception('name is too long');
}
return $name;
}
private function round2(float $value): float
{
return round($value, 2);
}
private function computeKcal100(float $protein_g_100, float $carbs_g_100, float $fat_g_100): float
{
return $this->round2($protein_g_100 * 4 + $carbs_g_100 * 4 + $fat_g_100 * 9);
}
private function getMealOwned(int $user_id, int $meal_id): array
{
$meal = $this->meals()->meal($meal_id);
if (!is_array($meal)) {
throw new \Exception('Meal not found');
}
if ((int) $meal['user_id'] !== $user_id) {
throw new \Exception('Meal does not belong to user');
}
return $meal;
}
private function getIngredientAccessible(int $user_id, int $ingredient_id): array
{
$ingredient = $this->ingredients()->ingredient($ingredient_id);
if (!is_array($ingredient)) {
throw new \Exception('Ingredient not found');
}
if (!is_null($ingredient['user_id']) && (int) $ingredient['user_id'] !== $user_id) {
throw new \Exception('Ingredient is not accessible for user');
}
return $ingredient;
}
private function getIngredientOwned(int $user_id, int $ingredient_id): array
{
$ingredient = $this->ingredients()->ingredient($ingredient_id);
if (!is_array($ingredient)) {
throw new \Exception('Ingredient not found');
}
if (is_null($ingredient['user_id']) || (int) $ingredient['user_id'] !== $user_id) {
throw new \Exception('Ingredient does not belong to user');
}
return $ingredient;
}
private function getMealItemOwned(int $user_id, int $meal_item_id): array
{
$item = $this->mealItems()->mealItem($meal_item_id);
if (!is_array($item)) {
throw new \Exception('Meal item not found');
}
$this->getMealOwned($user_id, (int) $item['meal_id']);
return $this->mapMealItem($item);
}
private function buildMealItems(int $meal_id, bool $with_calculated = true): array
{
$rows = $this->mealItems()->search('mealItems')
->where(array('meal_id' => $meal_id))
->order(array('position' => 'ASC', 'meal_item_id' => 'ASC'))
->toArray();
$rows = is_array($rows) ? $rows : array();
$result = array();
foreach ($rows as $row) {
$item = $this->mapMealItem($row);
if ($with_calculated) {
$item = $this->enrichMealItem($item);
}
$result[] = $item;
}
return $result;
}
private function enrichMealItem(array $item): array
{
$ingredient = $this->ingredients()->ingredient((int) $item['ingredient_id']);
if (!is_array($ingredient)) {
throw new \Exception('Ingredient for meal item was not found');
}
$ingredient = $this->mapIngredient($ingredient);
$factor = ((float) $item['grams']) / 100;
$kcal100 = (float) $ingredient['kcal_100'];
if ($kcal100 <= 0) {
$kcal100 = $this->computeKcal100(
(float) $ingredient['protein_g_100'],
(float) $ingredient['carbs_g_100'],
(float) $ingredient['fat_g_100']
);
}
$item['ingredient'] = $ingredient;
$item['nutrition'] = array(
'protein_g' => $this->round2(((float) $ingredient['protein_g_100']) * $factor),
'carbs_g' => $this->round2(((float) $ingredient['carbs_g_100']) * $factor),
'sugar_g' => $this->round2(((float) $ingredient['sugar_g_100']) * $factor),
'fat_g' => $this->round2(((float) $ingredient['fat_g_100']) * $factor),
'fiber_g' => $this->round2(((float) $ingredient['fiber_g_100']) * $factor),
'kcal' => $this->round2($kcal100 * $factor)
);
return $item;
}
private function calculateMealTotals(int $meal_id): array
{
$items = $this->buildMealItems($meal_id, true);
return $this->totalsFromCalculatedItems($items);
}
private function totalsFromCalculatedItems(array $items): array
{
$totals = $this->emptyTotals();
foreach ($items as $item) {
if (!isset($item['nutrition']) || !is_array($item['nutrition'])) {
continue;
}
$totals = $this->addTotals($totals, $item['nutrition']);
}
return $totals;
}
private function emptyTotals(): array
{
return array(
'protein_g' => 0.0,
'carbs_g' => 0.0,
'sugar_g' => 0.0,
'fat_g' => 0.0,
'fiber_g' => 0.0,
'kcal' => 0.0
);
}
private function addTotals(array $base, array $add): array
{
foreach ($base as $key => $value) {
$base[$key] = $this->round2((float) $value + (float) ($add[$key] ?? 0));
}
return $base;
}
private function getDiaryDay(int $user_id, string $day_date): array|false
{
$rows = $this->diaryDays()->getList(array(
'user_id' => $user_id,
'day_date' => $day_date
));
if (!is_array($rows) || count($rows) <= 0) {
return false;
}
return $rows[0];
}
private function ensureDiaryDay(int $user_id, string $day_date): array
{
$day = $this->getDiaryDay($user_id, $day_date);
if (is_array($day)) {
return $this->mapDiaryDay($day);
}
$dayId = $this->diaryDays()->diaryDaySave(array(
'user_id' => $user_id,
'day_date' => $day_date,
'created_at' => '`NOW`'
));
if ($dayId === false) {
throw new \Exception('Failed to create diary day');
}
$created = $this->diaryDays()->diaryDay((int) $dayId);
if (!is_array($created)) {
throw new \Exception('Failed to load created diary day');
}
return $this->mapDiaryDay($created);
}
private function buildDiaryDay(int $user_id, string $day_date, bool $with_totals): array
{
$day = $this->getDiaryDay($user_id, $day_date);
if (!is_array($day)) {
$ret = array(
'user_id' => $user_id,
'day_date' => $day_date,
'diary_day_id' => null,
'entries' => array()
);
if ($with_totals) {
$ret['totals'] = $this->emptyTotals();
}
return $ret;
}
$day = $this->mapDiaryDay($day);
$entriesRows = $this->diaryEntries()->search('diaryEntries')
->where(array('diary_day_id' => (int) $day['diary_day_id']))
->order(array('diary_entry_id' => 'ASC'))
->toArray();
$entriesRows = is_array($entriesRows) ? $entriesRows : array();
$entries = array();
$totals = $this->emptyTotals();
foreach ($entriesRows as $row) {
$entry = $this->mapDiaryEntry($row);
$meal = $this->mapMeal($this->getMealOwned($user_id, (int) $entry['meal_id']));
$entry['meal'] = $meal;
if ($with_totals) {
$mealTotals = $this->calculateMealTotals((int) $entry['meal_id']);
$entry['meal_totals'] = $mealTotals;
$totals = $this->addTotals($totals, $mealTotals);
}
$entries[] = $entry;
}
$ret = array(
'user_id' => $user_id,
'day_date' => $day_date,
'diary_day_id' => (int) $day['diary_day_id'],
'entries' => $entries
);
if ($with_totals) {
$ret['totals'] = $totals;
}
return $ret;
}
private function mapIngredient(array $row): array
{
$row['ingredient_id'] = (int) $row['ingredient_id'];
$row['user_id'] = is_null($row['user_id']) ? null : (int) $row['user_id'];
$row['protein_g_100'] = $this->round2((float) $row['protein_g_100']);
$row['carbs_g_100'] = $this->round2((float) $row['carbs_g_100']);
$row['sugar_g_100'] = $this->round2((float) $row['sugar_g_100']);
$row['fat_g_100'] = $this->round2((float) $row['fat_g_100']);
$row['fiber_g_100'] = $this->round2((float) $row['fiber_g_100']);
$row['kcal_100'] = $this->round2((float) $row['kcal_100']);
return $row;
}
private function mapMeal(array $row): array
{
$row['meal_id'] = (int) $row['meal_id'];
$row['user_id'] = (int) $row['user_id'];
return $row;
}
private function mapMealItem(array $row): array
{
$row['meal_item_id'] = (int) $row['meal_item_id'];
$row['meal_id'] = (int) $row['meal_id'];
$row['ingredient_id'] = (int) $row['ingredient_id'];
$row['grams'] = $this->round2((float) $row['grams']);
$row['position'] = (int) $row['position'];
return $row;
}
private function mapDiaryDay(array $row): array
{
$row['diary_day_id'] = (int) $row['diary_day_id'];
$row['user_id'] = (int) $row['user_id'];
return $row;
}
private function mapDiaryEntry(array $row): array
{
$row['diary_entry_id'] = (int) $row['diary_entry_id'];
$row['diary_day_id'] = (int) $row['diary_day_id'];
$row['meal_id'] = (int) $row['meal_id'];
return $row;
}
}