ldc-ovoteam/app/Http/Controllers/Back/ProductController.php
Jérémy Munsch ca9c0fbc4e
feat(policy): allow ProductDto and RecipeDto in policies
Updated ProductPolicy and RecipePolicy to accept ProductDto in addition to Product. This change enhances the flexibility of the policies by allowing DTOs to be used for authorization checks.

refactor(provider): simplify service provider bindings

Refactored AppServiceProvider to simplify the binding of ProductDirectory and RecipeDirectory. Removed unnecessary dependencies and improved clarity.

feat(route): update route bindings for front-end

Changed route bindings for products and recipes to use frontProduct and frontRecipe. This improves clarity and consistency in route handling.

fix(breadcrumbs): update breadcrumb checks for DTOs

Updated breadcrumb generation to check for ProductDto and RecipeDto instead of their model counterparts. This ensures breadcrumbs function correctly with the new DTO structure.

refactor(types): remove FilePath type and update schemas

Removed the FilePath type definition and updated related schemas to use string directly. This simplifies type handling for file paths.

style(entities): standardize naming conventions

Updated naming conventions in Product and Recipe entities to use snake_case for consistency across the codebase.

feat(frontend): update product and recipe pages for new DTO structure

Modified front-end components to accommodate changes in the product and recipe data structures, ensuring compatibility with the new DTOs.
2026-11-05 16:49:42 +01:00

225 lines
9 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Http\Controllers\Back;
use App\Contracts\Executor;
use App\Cqs\Actions\Products\Create\CreateProduct;
use App\Cqs\Actions\Products\Delete\DeleteProduct;
use App\Cqs\Actions\Products\Delete\DeleteProductInput;
use App\Cqs\Actions\Products\ForceDelete\ForceDeleteProduct;
use App\Cqs\Actions\Products\ForceDelete\ForceDeleteProductInput;
use App\Cqs\Actions\Products\Restore\RestoreProduct;
use App\Cqs\Actions\Products\Restore\RestoreProductInput;
use App\Cqs\Actions\Products\Update\UpdateProduct;
use App\Cqs\Queries\Products\GetBoPaginatedProductsQuery;
use App\Dto\ProductDto;
use App\Http\Requests\Back\Products\IndexProductRequest;
use App\Http\Requests\Back\Products\StoreProductRequest;
use App\Http\Requests\Back\Products\UpdateProductRequest;
use App\Http\Resources\CommonResource;
use App\Models\Product;
use Domain\Models\ValueObjects\Entities\ProductId;
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\Contracts\Session\Session;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
use Inertia\Response;
class ProductController extends BackendController
{
public function __construct(
Request $request,
Session $session,
private readonly Executor $executor
) {
parent::__construct(
$request,
$session
);
$this->modelName = Product::modelName();
$this->modelPage = Product::modelPage();
}
public function index(IndexProductRequest $request, GetBoPaginatedProductsQuery $query): Response
{
$this->authorize('viewAny', Product::class);
$output = $this->executor->execute($query, $request->toGetBoPaginatedProductsQueryInput());
return $this->inertiaRender('back/Pages/Products/Index', [
'paginatedModels' => CommonResource::collection($output->paginatedProducts),
'search' => $output->search,
'searchFields' => $output->searchFields,
'enumProductCategory' => $output->categories,
'enumTechnology' => $output->technologies,
]);
}
public function show(ProductDto $product): RedirectResponse
{
$this->authorize('viewAny', Product::class);
return redirect()->route('back.products.edit', $product);
}
public function create(Product $product): Response
{
$this->authorize('create', Product::class);
return $this->inertiaRender('back/Pages/Products/Create', [
'data' => CommonResource::make($product),
'enumProductCategory' => ProductCategory::toArray(),
'enumTechnology' => Technology::toArray(),
'enumBreedingMethod' => BreedingMethod::toArray(),
'enumBusiness' => Business::toArray(),
'enumProductFormat' => ProductFormat::toArray(),
'enumNutritionnalUnit' => NutritionnalUnit::toArray(),
]);
}
public function store(StoreProductRequest $request, CreateProduct $createProduct): RedirectResponse
{
$this->authorize('create', Product::class);
$result = $this->executor->execute($createProduct, $request->toCreateProductInput());
return match (true) {
$result instanceof ProductId => redirect()->route('back.products.edit', $result)
->with('success', trans('uwil-backend::crud.messages.has_been_created', [
'model' => Str::ucfirst(trans_choice('models.classes.product', 1)),
])),
default => redirect()->back()
->with('error', trans('uwil-backend::crud.messages.cannot_be_created', [
'model' => Str::ucfirst(trans_choice('models.classes.product', 1)),
])),
};
}
public function edit(ProductDto $product): Response
{
$this->authorize('update', $product);
return $this->inertiaRender('back/Pages/Products/Edit', [
'data' => CommonResource::make($product),
'enumProductCategory' => ProductCategory::toArray(),
'enumTechnology' => Technology::toArray(),
'enumBreedingMethod' => BreedingMethod::toArray(),
'enumBusiness' => Business::toArray(),
'enumProductFormat' => ProductFormat::toArray(),
'enumNutritionnalUnit' => NutritionnalUnit::toArray(),
]);
}
public function update(
UpdateProductRequest $request,
ProductDto $product,
UpdateProduct $updateProduct,
): RedirectResponse {
$this->authorize('update', $product);
$result = $this->executor->execute($updateProduct, $request->toUpdateProductInput($product));
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(ProductDto $product): Response
{
$model = Product::withTrashed()->findOrFail($product->id);
return $this->create($model->replicate());
}
public function restore(string $id, RestoreProduct $restoreProduct): RedirectResponse
{
$product = Product::withTrashed()->findOrFail($id);
$this->authorize('restore', $product);
$previousQueries = $this->getPreviousQueries();
$result = $this->executor->execute($restoreProduct, new RestoreProductInput($product->getId()));
return match (true) {
$result instanceof ProductId => redirect()->route('back.products.trash', $previousQueries)
->with('success', trans('uwil-backend::crud.messages.has_been_restored', [
'model' => Str::ucfirst(trans_choice('models.classes.product', 1)),
])),
default => redirect()->back()
->with('error', trans('uwil-backend::crud.messages.cannot_be_restored', [
'model' => Str::ucfirst(trans_choice('models.classes.product', 1)),
])),
};
}
public function destroy(ProductDto $product, DeleteProduct $deleteProduct): RedirectResponse
{
$this->authorize('delete', $product);
$previousQueries = $this->getPreviousQueries();
$result = $this->executor->execute($deleteProduct, new DeleteProductInput($product->getId()));
return match (true) {
$result instanceof ProductId => redirect()->route('back.products.index', $previousQueries)
->with('success', trans('uwil-backend::crud.messages.has_been_deleted', [
'model' => Str::ucfirst(trans_choice('models.classes.product', 1)),
])),
default => redirect()->back()
->with('error', trans('uwil-backend::crud.messages.cannot_be_deleted', [
'model' => Str::ucfirst(trans_choice('models.classes.product', 1)),
])),
};
}
public function forceDestroy(string $id, ForceDeleteProduct $forceDeleteProduct): RedirectResponse
{
$product = Product::withTrashed()->findOrFail($id);
$this->authorize('forceDelete', $product);
$previousQueries = $this->getPreviousQueries();
$result = $this->executor->execute($forceDeleteProduct, new ForceDeleteProductInput($product->getId()));
return match (true) {
$result instanceof ProductId => redirect()->route('back.products.trash', $previousQueries)
->with('success', trans('uwil-backend::crud.messages.has_been_deleted', [
'model' => Str::ucfirst(trans_choice('models.classes.product', 1)),
])),
default => redirect()->back()
->with('error', trans('uwil-backend::crud.messages.cannot_be_deleted', [
'model' => Str::ucfirst(trans_choice('models.classes.product', 1)),
])),
};
}
/** @return array<array-key,string|array<mixed>> */
private function getPreviousQueries(): array
{
$previousQueries = [];
$previousQueryString = \parse_url($this->getPreviousUrl(), \PHP_URL_QUERY) ?? '' ?: '';
\parse_str($previousQueryString, $previousQueries);
return $previousQueries;
}
private function getPreviousUrl(): string
{
return url()->previous(route('back.dashboard.index'));
}
}