refactor(requests): simplify nutritional values handling in product requests
Updated the handling of nutritional values in StoreProductRequest and UpdateProductRequest to improve clarity and maintainability. The logic for processing nutritional values has been centralized into a dedicated method, enhancing code readability.
This commit is contained in:
parent
8f9bf1e861
commit
481d80c8ea
7 changed files with 124 additions and 55 deletions
|
|
@ -20,7 +20,7 @@ final readonly class CreateProductInput implements ActionInput
|
|||
* @param BreedingMethod[] $breedingMethods
|
||||
* @param Business[] $businesses
|
||||
* @param ProductFormat[] $formats
|
||||
* @param array{unit: NutritionnalUnit, value: string}[] $nutritionalValues
|
||||
* @param array<string, array{unit: NutritionnalUnit, value: string}> $nutritionalValues
|
||||
*/
|
||||
public function __construct(
|
||||
public string $name,
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ final readonly class UpdateProductInput implements ActionInput
|
|||
* @param BreedingMethod[] $breedingMethods
|
||||
* @param Business[] $businesses
|
||||
* @param ProductFormat[] $formats
|
||||
* @param array{unit: NutritionnalUnit, value: string}[] $nutritionalValues
|
||||
* @param array<string, array{unit: NutritionnalUnit, value: string}> $nutritionalValues
|
||||
*/
|
||||
public function __construct(
|
||||
public ProductId $id,
|
||||
|
|
|
|||
|
|
@ -123,18 +123,21 @@ class ProductController extends BackendController
|
|||
UpdateProductRequest $request,
|
||||
Product $product,
|
||||
UpdateProduct $updateProduct,
|
||||
): ProductDto {
|
||||
): RedirectResponse {
|
||||
$this->authorize('update', $product);
|
||||
|
||||
$result = $this->executor->execute($updateProduct, $request->toUpdateProductInput($product));
|
||||
|
||||
if (! $result instanceof ProductDto) {
|
||||
abort(500, trans('uwil-backend::crud.messages.cannot_be_updated', [
|
||||
'model' => Str::ucfirst(trans_choice('models.classes.product', 1)),
|
||||
]));
|
||||
}
|
||||
|
||||
return $result;
|
||||
return match (true) {
|
||||
$result instanceof ProductDto => redirect()->route('back.products.edit', $product)
|
||||
->with('success', trans('uwil-backend::crud.messages.has_been_updated', [
|
||||
'model' => Str::ucfirst(trans_choice('models.classes.product', 1)),
|
||||
])),
|
||||
default => redirect()->route('back.products.edit', $product)
|
||||
->with('error', trans('uwil-backend::crud.messages.cannot_be_updated', [
|
||||
'model' => Str::ucfirst(trans_choice('models.classes.product', 1)),
|
||||
])),
|
||||
};
|
||||
}
|
||||
|
||||
public function duplicate(Product $product): Response
|
||||
|
|
|
|||
|
|
@ -128,18 +128,21 @@ class RecipeController extends BackendController
|
|||
UpdateRecipeRequest $request,
|
||||
Recipe $recipe,
|
||||
UpdateRecipe $updateRecipe,
|
||||
): RecipeDto {
|
||||
): RedirectResponse {
|
||||
$this->authorize('update', $recipe);
|
||||
|
||||
$result = $this->executor->execute($updateRecipe, $request->toUpdateRecipeInput($recipe));
|
||||
|
||||
if (! $result instanceof RecipeDto) {
|
||||
abort(500, trans('uwil-backend::crud.messages.cannot_be_updated', [
|
||||
'model' => Str::ucfirst(trans_choice('models.classes.recipe', 1)),
|
||||
]));
|
||||
}
|
||||
|
||||
return $result;
|
||||
return match (true) {
|
||||
$result instanceof RecipeDto => redirect()->route('back.recipes.edit', $recipe)
|
||||
->with('success', trans('uwil-backend::crud.messages.has_been_updated', [
|
||||
'model' => Str::ucfirst(trans_choice('models.classes.recipe', 1)),
|
||||
])),
|
||||
default => redirect()->route('back.recipes.edit', $recipe)
|
||||
->with('error', trans('uwil-backend::crud.messages.cannot_be_updated', [
|
||||
'model' => Str::ucfirst(trans_choice('models.classes.recipe', 1)),
|
||||
])),
|
||||
};
|
||||
}
|
||||
|
||||
public function duplicate(Recipe $recipe, GetProductsSummariesQuery $getProductsSummaries): Response
|
||||
|
|
|
|||
|
|
@ -4,12 +4,11 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Http\Middlewares;
|
||||
|
||||
use App\Lib\PublicS3Disk;
|
||||
use Closure;
|
||||
use Illuminate\Contracts\Container\Container;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Config;
|
||||
use Illuminate\Support\Facades\Vite;
|
||||
use Illuminate\Support\Str;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class SecureHeaders
|
||||
|
|
@ -36,7 +35,7 @@ class SecureHeaders
|
|||
*
|
||||
* @param \Closure(\Illuminate\Http\Request):(\Illuminate\Http\Response) $next
|
||||
*/
|
||||
public function handle(Request $request, Closure $next): Response
|
||||
public function handle(Request $request, \Closure $next): Response
|
||||
{
|
||||
$appUrl = Config::string('app.url');
|
||||
$appDebug = Config::boolean('app.debug');
|
||||
|
|
@ -67,7 +66,8 @@ class SecureHeaders
|
|||
$response->headers->set('X-Frame-Options', 'SAMEORIGIN');
|
||||
$response->headers->set('Strict-Transport-Security', 'max-age=31536000; includeSubDomains; preload');
|
||||
|
||||
$s3PublicEndpoint = $this->container->make(PublicS3Disk::class)->urlEndpoint;
|
||||
$s3PublicEndpoint = Str::of(Config::string('filesystems.disks.s3.url'))
|
||||
->chopEnd('/')->append('/')->value();
|
||||
|
||||
// * Ignore CSP on some conditions.
|
||||
if (
|
||||
|
|
|
|||
|
|
@ -47,6 +47,20 @@ class StoreProductRequest extends FormRequest
|
|||
|
||||
public function toCreateProductInput(): CreateProductInput
|
||||
{
|
||||
$picture = null;
|
||||
if ($this->hasFile('picture')) {
|
||||
$picture = $this->storeFile($this->file('picture'));
|
||||
} elseif ($this->filled('picture')) {
|
||||
$picture = new StorageFilePath($this->string('picture')->value());
|
||||
}
|
||||
|
||||
$pdf = null;
|
||||
if ($this->hasFile('pdf')) {
|
||||
$pdf = $this->storeFile($this->file('pdf'));
|
||||
} elseif ($this->filled('pdf')) {
|
||||
$pdf = new StorageFilePath($this->string('pdf')->value());
|
||||
}
|
||||
|
||||
return new CreateProductInput(
|
||||
name: $this->string('name')->trim()->value(),
|
||||
seoTitle: $this->string('seo_title')->trim()->value(),
|
||||
|
|
@ -79,21 +93,11 @@ class StoreProductRequest extends FormRequest
|
|||
conservationBeforeOpening: $this->string('conservation_before_opening')->trim()->value(),
|
||||
conservationAfterOpening: $this->filled('conservation_after_opening') ?
|
||||
$this->string('conservation_after_opening')->trim()->value() : null,
|
||||
picture: $this->hasFile('picture') ? $this->storeFile($this->file('picture')) : null,
|
||||
picture: $picture,
|
||||
pictureAlt: $this->string('picture_alt')->trim()->value(),
|
||||
pictureTitle: $this->string('picture_title')->trim()->value(),
|
||||
pdf: $this->hasFile('pdf') ? $this->storeFile($this->file('pdf')) : null,
|
||||
nutritionalValues: array_map(
|
||||
function ($value) {
|
||||
$value = $this->mixedToArray($value);
|
||||
|
||||
return [
|
||||
'unit' => NutritionnalUnit::from(Arr::string($value, 'unit')),
|
||||
'value' => Arr::string($value, 'value'),
|
||||
];
|
||||
},
|
||||
$this->array('nutritional_values')
|
||||
),
|
||||
pdf: $pdf,
|
||||
nutritionalValues: $this->getNutritionalValues(),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -102,7 +106,7 @@ class StoreProductRequest extends FormRequest
|
|||
*/
|
||||
protected function prepareForValidation(): void
|
||||
{
|
||||
$this->merge([
|
||||
$merges = [
|
||||
'name' => $this->string('name')->trim()->value(),
|
||||
'seo_title' => $this->string('seo_title')->trim()->value(),
|
||||
'seo_description' => $this->string('seo_description')->trim()->value(),
|
||||
|
|
@ -110,7 +114,27 @@ class StoreProductRequest extends FormRequest
|
|||
'picture_title' => $this->string('picture_title')->trim()->value(),
|
||||
'conservation_before_opening' => $this->string('conservation_before_opening')->trim()->value(),
|
||||
'conservation_after_opening' => $this->string('conservation_after_opening')->trim()->value() ?: null,
|
||||
]);
|
||||
];
|
||||
|
||||
if ($this->has('nutritional_values') && is_array($this->input('nutritional_values'))) {
|
||||
$nutritionalValues = $this->array('nutritional_values');
|
||||
foreach ($nutritionalValues as $key => $item) {
|
||||
$value = (is_array($item) && isset($item['value']) && is_numeric($item['value'])) ?
|
||||
$this->mixedToString($item['value']) : null;
|
||||
|
||||
if ($value !== null) {
|
||||
$nutValue = when(
|
||||
is_array($item) && isset($item['value']) && is_numeric($item['value']),
|
||||
fn () => $this->mixedToString($item['value']),
|
||||
fn () => null
|
||||
);
|
||||
$nutritionalValues[$key] = $nutValue;
|
||||
}
|
||||
}
|
||||
$merges['nutritional_values'] = $nutritionalValues;
|
||||
}
|
||||
|
||||
$this->merge($merges);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -225,13 +249,64 @@ class StoreProductRequest extends FormRequest
|
|||
return (string) $value;
|
||||
}
|
||||
|
||||
/** @return array<array-key,mixed> */
|
||||
protected function mixedToArray(mixed $value): array
|
||||
/**
|
||||
* @return array<string, array{unit: NutritionnalUnit, value: string}>
|
||||
*/
|
||||
public function getNutritionalValues(): array
|
||||
{
|
||||
if (! is_array($value)) {
|
||||
throw new \InvalidArgumentException('Value must be an array to convert to array.');
|
||||
$raw = $this->input('nutritional_values');
|
||||
|
||||
if (! is_array($raw) || $raw === []) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $value;
|
||||
$result = [];
|
||||
|
||||
foreach ($raw as $key => $item) {
|
||||
if (! is_array($item)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$rawUnit = Arr::get($item, 'unit');
|
||||
$rawValue = Arr::get($item, 'value');
|
||||
|
||||
if ($rawUnit === null || $rawValue === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$unit = $rawUnit instanceof NutritionnalUnit
|
||||
? $rawUnit
|
||||
: NutritionnalUnit::tryFrom($this->mixedToString($rawUnit));
|
||||
|
||||
$value = mb_trim($this->mixedToString($rawValue));
|
||||
|
||||
if ($unit === null || $value === '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$result[(string) $key] = [
|
||||
'unit' => $unit,
|
||||
'value' => $value,
|
||||
];
|
||||
}
|
||||
|
||||
$nutrients = array_filter(
|
||||
$result,
|
||||
fn (string $k) => $k !== 'refWeightG',
|
||||
ARRAY_FILTER_USE_KEY
|
||||
);
|
||||
|
||||
if (empty($nutrients)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (! isset($result['refWeightG'])) {
|
||||
$result['refWeightG'] = [
|
||||
'unit' => NutritionnalUnit::GRAM,
|
||||
'value' => '100',
|
||||
];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,11 +8,9 @@ use App\Cqs\Actions\Products\Update\UpdateProductInput;
|
|||
use App\Models\Product;
|
||||
use Domain\Models\ValueObjects\Products\BreedingMethod;
|
||||
use Domain\Models\ValueObjects\Products\Business;
|
||||
use Domain\Models\ValueObjects\Products\NutritionnalUnit;
|
||||
use Domain\Models\ValueObjects\Products\ProductCategory;
|
||||
use Domain\Models\ValueObjects\Products\ProductFormat;
|
||||
use Domain\Models\ValueObjects\Products\Technology;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Uwil\Storage\Lib\ValueObjects\StorageFilePath;
|
||||
|
|
@ -81,17 +79,7 @@ class UpdateProductRequest extends StoreProductRequest
|
|||
pictureAlt: $this->string('picture_alt')->trim()->value(),
|
||||
pictureTitle: $this->string('picture_title')->trim()->value(),
|
||||
pdf: $pdf,
|
||||
nutritionalValues: array_map(
|
||||
function ($value) {
|
||||
$value = $this->mixedToArray($value);
|
||||
|
||||
return [
|
||||
'unit' => NutritionnalUnit::from(Arr::string($value, 'unit')),
|
||||
'value' => Arr::string($value, 'value'),
|
||||
];
|
||||
},
|
||||
$this->array('nutritional_values')
|
||||
),
|
||||
nutritionalValues: $this->getNutritionalValues(),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue