<?php
namespace App\Controller;
use DateTime;
use App\Entity\User;
use App\Entity\Image;
use Twig\Environment;
use App\Entity\Magasin;
use App\Entity\Produit;
use App\Entity\Category;
use App\Data\SearchData;
use App\Form\SearchForm;
use App\Data\ShopContext;
use App\Form\ProductType;
use App\Service\PictureService;
use Doctrine\ORM\EntityRepository;
use App\Entity\MaintenanceSchedule;
use App\Repository\ProduitRepository;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\Persistence\ManagerRegistry;
use App\Controller\ProduitVariantController;
use App\Repository\ProduitVariantRepository;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Translation\Translator;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Csrf\CsrfToken;
use Symfony\Component\Routing\Annotation\Route;
use App\Repository\MaintenanceScheduleRepository;
use Symfony\Component\Translation\LocaleSwitcher;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Contracts\Translation\TranslatorInterface;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
class ProduitController extends AbstractController
{
private CsrfTokenManagerInterface $csrfTokenManager;
private $params;
private $shopContext;
public function __construct(CsrfTokenManagerInterface $csrfTokenManager,
ShopContext $shopContext)
{
$this->csrfTokenManager = $csrfTokenManager;
$this->shopContext = $shopContext;
}
public function validateCsrfToken($token): bool
{
return $this->csrfTokenManager->isTokenValid(new CsrfToken('my-form-promo', $token));
}
#[Route('/locale/{_locale}', name: 'app_locale')]
public function setLocale(Request $request,SessionInterface $session
,TranslatorInterface $translator,LocaleSwitcher $localeSwitcher ):Response
{
$locale = $request->get('_locale');
$currentLocale = $localeSwitcher->getLocale();
if($locale !=null){
$localeSwitcher->setLocale($locale);
$translator->setLocale($locale);
$request->getSession()->set('_locale',$locale);
}
$sessionlocal= $request->getSession()->get('_locale');
return $this->redirectToRoute("app_home",['_locale'=>$sessionlocal]);
}
#[Route(path: ['/home/{shopName}', '/home'], name: 'app_home',
defaults: ['shopName' => null]
)]
public function index(ManagerRegistry $doctrine, Request $request
,?string $shopName
,Environment $twig,Security $security,SessionInterface $session
,TranslatorInterface $translator,LocaleSwitcher $localeSwitcher
,EntityManagerInterface $entityManager):Response
{
if ($request->getSession()->has('_locale')) {
$locale = $request->getSession()->get('_locale');
if($locale !=null){
$localeSwitcher->setLocale($locale);
$translator->setLocale($locale);
$request->getSession()->set('lang',$locale);
}
}
else {
$request->getSession()->set('_locale','en');
$request->getSession()->set('lang','en');
$locale = 'en';
if($locale !=null){
$localeSwitcher->setLocale($locale);
$translator->setLocale($locale);
}
}
$session->set('srv_msg',null);
$shops = [];
if ($shopName) {
$slugs = explode(',', $shopName);
$shops = $entityManager->getRepository(Magasin::class)->findBy(['nom' => $slugs]);
if (!$shops) {
throw $this->createNotFoundException('Aucune boutique trouvée');
}
$this->shopContext->setShops($shops);
} elseif ($request->query->get('shopName')) {
$shops = $entityManager->getRepository(Magasin::class)->findBy(['nom' => [$request->query->get('shopName')]]);
$this->shopContext->setShops($shops);
} else {
$this->shopContext->clear();
}
$lastActive= $doctrine->getRepository(MaintenanceSchedule::class)
->findLastActiveSchedule();
if ($lastActive) {
return $this->redirectToRoute("maintenance_index",['_locale'=>$locale,'lastActiveId'=>$lastActive->getId()]);
}
$data = new SearchData();
$form = $this->createForm(SearchForm::class, $data);
$form->handleRequest($request);
$data->categories = $request->query->all('categories');
$data->shops = $shops;
$data->promo = $request->query->get('promo');
// ── NEW: also read min/max/q from GET for filter sidebar ──
if (!$form->isSubmitted()) {
$data->q = $request->query->get('q');
$data->min = $request->query->get('min');
$data->max = $request->query->get('max');
}
$offset = max(0, $request->query->getInt('offset', 0));
$findProduitsNouveaute = [];
$isAdmin = 0;
$user = $security->getUser();
if($user){
$roles = $user->getRoles();
if($roles[0] == "ROLE_ADMIN"){
$isAdmin=1;
}
}
else{
$isAdmin=0;
}
if($form->isSubmitted() && $form->isValid() ){
$produits = $doctrine->getRepository(Produit::class)->findSearch($data,$offset,$isAdmin);
$magasins = $doctrine->getRepository(Magasin::class)->findAll();
}else{
$category = $request->request->get('category', null);
if($category !=null){
$data = new SearchData();
$categories = [$category];
$data->categories = $categories;
}
else{
$findProduitsNouveaute = $doctrine->getRepository(Produit::class)
->findProduitsNouveaute($data,$offset,$isAdmin);
}
$produits = $doctrine->getRepository(Produit::class)->findSearch($data,$offset,$isAdmin);
$magasins = $doctrine->getRepository(Magasin::class)->findAll();
}
// ── NEW: pass all categories for filter sidebar ──
$allCategories = $entityManager->getRepository(Category::class)
->findBy([], ['nom' => 'ASC']);
// ── NEW: count active filters for badge ──
$activeFilters = 0;
if (!empty($data->q)) $activeFilters++;
if (!empty($data->categories)) $activeFilters++;
if (!empty($data->promo)) $activeFilters++;
if (!empty($data->min)) $activeFilters++;
if (!empty($data->max)) $activeFilters++;
return new Response($twig->render('produit/index.html.twig',[
'produits' => $produits,
'magasins' => $magasins,
'_locale' => $locale,
'produitsNouveaute' => $findProduitsNouveaute,
'form' => $form->createView(),
'previous' => $offset - ProduitRepository::PAGINATOR_PER_PAGE,
'next' => min(count($produits), $offset + ProduitRepository::PAGINATOR_PER_PAGE),
// ── NEW variables for filter sidebar ──
'allCategories' => $allCategories,
'activeFilters' => $activeFilters,
'currentQ' => $data->q ?? '',
'currentMin' => $data->min ?? '',
'currentMax' => $data->max ?? '',
'currentPromo' => $data->promo ?? '',
'currentCategories' => $data->categories ?? [],
'currentSort' => $request->query->get('sort', ''),
]));
}
#[Route('/produits/ajax-filter', name: 'ajax_product_filter', methods: ['POST'])]
public function ajaxFilterProducts(Request $request,
CsrfTokenManagerInterface $csrfTokenManager,
ProduitRepository $produitRepository,ManagerRegistry $doctrine,
Environment $twig,Security $security,SessionInterface $session,
TranslatorInterface $translator,LocaleSwitcher $localeSwitcher): JsonResponse
{
$csrfToken = $request->headers->get('X-CSRF-TOKEN');
if (!$this->validateCsrfToken($csrfToken)) {
return new JsonResponse(['error' => 'Invalid CSRF token'], 400);
}
$data = new SearchData();
$data->q = $request->request->get('q');
$data->categories = $request->request->get('categories');
$data->promo = $request->request->get('promo');
$data->min = $request->request->get('min');
$data->max = $request->request->get('max');
$data->dateproduction = $request->request->get('dateproduction');
$data->dateproduction = $request->request->get('dateexpiration');
$findProduitsPromo= [];
$isAdmin = 0;
$user = $security->getUser();
if($user){
$roles = $user->getRoles();
if($roles[0] == "ROLE_ADMIN"){
$isAdmin=1;
}
}
else{
$isAdmin=0;
}
$products = $produitRepository->findSearchPromo($data,$isAdmin);
$productData = [];
foreach ($products as $product) {
$productData[] = [
'id' => $product->getId(),
'name' => $product->getProductName(),
];
}
return new JsonResponse($productData);
}
#[Route('/produit/add', name: 'add_produit')]
#[Route('/produit/edit/{id}', name: 'edit_produit')]
public function new_edit(int $id =null ,Request $request,EntityManagerInterface $entityManager,Produit $produit = null,
PictureService $pictureService,ParameterBagInterface $params
,TranslatorInterface $translator,LocaleSwitcher $localeSwitcher ): Response
{
$this->denyAccessUnlessGranted('ROLE_ADMIN');
if ($id!=null){
$produit = $entityManager->getRepository(Produit::class)->find($id);
}
if (!$produit) {
$produit = new Produit();
$produitVariants = $produit->getProduitVariants();
$option = "add";
}
else{
$option = "edit";
}
$form = $this->createForm(ProductType::class, $produit);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$produit = $form->getData();
$images = $form->get('images')->getData();
foreach($images as $image){
$folder = 'products';
$fichier = $pictureService->add($image, $folder, 300, 300);
$img = new Image();
$img->setFileName($fichier);
$pictureService = new PictureService($params);
$img->setImageUrl($params->get('images_directory') . $folder);
$produit->addImage($img);
}
$produit->setUser($this->getUser());
$produitVariants = $form->get('produitVariants')->getData();
foreach($produitVariants as $produitVariant){
$produitVariant->setProduit($produit);
$produit->addProduitVariant($produitVariant);
}
$date = new DateTime();
$produit->setPublishDate( $date);
try{
$entityManager->persist($produit);
}
catch (Exception $e) {
$this->addFlash('error', 'An error occurred while saving the entity.');
}
$entityManager->flush();
if ($option === 'edit') {
return $this->redirectToRoute($option . '_produit', [
'id' => $produit->getId(),
]);
} else {
return $this->redirectToRoute($option.'_produit');
}
}
if ($request->query->has('_locale')) {
$locale = $request->getSession()->get('_locale');
if($locale !=null){
$localeSwitcher->setLocale($locale);
$translator->setLocale($locale);
}
}
return $this->render('produit/add.html.twig', [
'formAddProduit' => $form->createView(),
'option' => $option
]);
}
#[Route('/produit/{id}', name: 'show_produit')]
public function show( string $id,EntityManagerInterface $entityManager
,TranslatorInterface $translator,LocaleSwitcher $localeSwitcher , Request $request): Response
{
if ($id!=null){
$produit = $entityManager->getRepository(Produit::class)->find($id);
}
if (!$produit) {
throw $this->createNotFoundException('Product not found');
}
$locale = $request->getSession()->get('_locale');
if($locale !=null){
$localeSwitcher->setLocale($locale);
$translator->setLocale($locale);
}
$groupedVariantssize = [];
foreach ($produit->getProduitVariants() as $variant) {
$paramSize = $variant->getParamSize();
if ($paramSize !== null) {
$size = $paramSize->getSizeAbreviation();
if ($size !== null) {
$groupedVariantssize[$size][] = $variant;
}
}
}
$groupedVariantscolor = [];
foreach ($produit->getProduitVariants() as $variant) {
$paramColor = $variant->getParamColor();
if ($paramColor !== null) {
$color = $paramColor->getColorName();
if ($color !== null) {
$groupedVariantscolor[$color][] = $variant;
}
}
}
$variantsArray = [];
foreach ($produit->getProduitVariants() as $variant) {
if (($variant !== null && $variant->getParamColor() !== null) ) {
if ($variant->getParamColor() !== null) {
$variantsArray[$variant->getParamColor()->getColorName()] = [];
}
}
if ($variant !== null && $variant->getParamSize() !== null) {
$variantsArray[$variant->getParamColor()->getColorName()][] = $variant->getParamSize()->getSizeAbreviation();
}
}
return $this->render('produit/show.html.twig', [
'produit' => $produit,
'groupedVariantscolor' => $groupedVariantscolor,
'groupedVariantssize' => $groupedVariantssize,
'variants' =>$variantsArray
]);
}
}