src/Controller/ProductController.php line 64

Open in your IDE?
  1. <?php 
  2. declare(strict_types=1);
  3. namespace App\Controller;
  4. use Symfony\Component\HttpFoundation\Request;
  5. use Symfony\Component\HttpFoundation\Response;
  6. use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
  7. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  8. use Sylius\Component\Locale\Context\LocaleContextInterface;
  9. use Sylius\Component\Channel\Context\ChannelContextInterface;
  10. use Sylius\Component\Core\Repository\ProductVariantRepositoryInterface;
  11. use Sylius\Component\Taxonomy\Repository\TaxonRepositoryInterface;
  12. use Sylius\Bundle\CoreBundle\Form\Type\Order\AddToCartType;
  13. use WhiteOctober\BreadcrumbsBundle\Model\Breadcrumbs;
  14. use App\Services\PPMCErpSynchroService;
  15. use App\Doctrine\ORM\SiteFAQProductRepository;
  16. use App\Entity\Customer\Customer;
  17. use App\Entity\SiteProductOptionValueMatch;
  18. use App\Entity\SiteFAQProduct;
  19. use App\Entity\SiteShop;
  20. use App\Entity\SiteCollection;
  21. use Sylius\Component\Order\Context\CartContextInterface;
  22. use App\Controller\SiteCollectionController;
  23. class ProductController extends AbstractController
  24. {
  25.     public function showAction(
  26.         Request $request,
  27.         ChannelContextInterface $channelContext,
  28.         LocaleContextInterface $localeContext,
  29.         ProductVariantRepositoryInterface $productVariantRepository,
  30.         TaxonRepositoryInterface $taxonRepository,
  31.         SiteFAQProductRepository $siteFaqProductRepository,
  32.         Breadcrumbs $breadcrumbs,
  33.         CartContextInterface $cartContext,
  34.         PPMCErpSynchroService $ppmcErpSynchro,
  35.         $slug,
  36.         $id
  37.     ) {
  38.         $channel $channelContext->getChannel();
  39.         $locale $localeContext->getLocaleCode();
  40.         // Récupère la déclinaison produit
  41.         $variant $productVariantRepository->findOneById($id);
  42.        
  43.         // if($_SERVER['REMOTE_ADDR'] == '91.168.137.186') {
  44.         //     dump($variant);
  45.         //     exit();
  46.         // }
  47.         if (empty($variant)) {
  48.             throw new NotFoundHttpException("Cette déclinaison produit n'existe pas.");
  49.         }
  50.         $isAdmin intval($request->query->get('admin'));
  51.         if ($variant->isEnabled() == false && $isAdmin == 0) {
  52.             throw new NotFoundHttpException("Cette déclinaison produit est désactivée.");
  53.         }
  54.         // Vérifie si le produit parent appartient à ce canal
  55.         if ($variant->getProduct()->hasChannel($channel) == false) {
  56.             throw new NotFoundHttpException("Cette déclinaison produit n'appartient pas à ce canal.");
  57.         }
  58.         if ($slug != $variant->getSlug()) {
  59.             return $this->redirectToRoute('app_product_variant_show', [
  60.                 'slug' => $variant->getSlug(),
  61.                 'id' => $variant->getId()
  62.             ]);
  63.         }
  64.         // Ajoute la déclinaison dans les "produits déjà vu" 
  65.         $lastViewedProductVariantsIds $this->get('session')->get('lastViewedProductVariantsIds', []);
  66.         // FIXME parameter au lieu de "16" + passer ce parameter a twig
  67.         if (count($lastViewedProductVariantsIds) >= 16) {
  68.             array_shift($lastViewedProductVariantsIds);
  69.         }
  70.         array_push($lastViewedProductVariantsIds$variant->getId());
  71.         $this->get('session')->set('lastViewedProductVariantsIds'$lastViewedProductVariantsIds);
  72.         // Récupère les collections qui match (couleurs associées)
  73.         $em $this->get('doctrine')->getManager();
  74.         $matchingColors $em->getRepository(SiteProductOptionValueMatch::class)
  75.         ->findByProductOptionValue($variant->getOptionValues()->first());
  76.         shuffle($matchingColors);
  77.         // Récupère les collections qui match et qui 
  78.         // possède une page "collection" sur le site
  79.         $matchingColorsWithPage $em->getRepository(SiteCollection::class)
  80.         ->findByProductOptionValue(array_map(function ($row) {
  81.             return $row->getMatchedProductOptionValue();
  82.         }, $matchingColors));
  83.         // Récupération des accessoires
  84.         $associationAccessoire $variant->getProduct()->getAssociations()->filter(function ($row) {
  85.             return $row->getType()->getCode() == 'accessoire';
  86.         })->first();
  87.         $accessoires = [];
  88.         if (empty($associationAccessoire) == false) {
  89.             $accessoires $productVariantRepository->findVariantsByShapeAndColors(
  90.                 $channel,
  91.                 $associationAccessoire->getAssociatedProducts()->toArray(),
  92.                 $locale,
  93.                 array_map(function ($row) {
  94.                     if($row->getMatchedProductOptionValue()){
  95.                         return $row->getMatchedProductOptionValue()->getId();
  96.                     }
  97.                     return;                    
  98.                    
  99.                 }, $matchingColors),
  100.                 // nombre maximum d'éléments
  101.             );
  102.         }
  103.         // Récupération des produits associés à "J'ajoute ma petite touche"
  104.         // puis récupère des déclinaisons qui correspondent à des collections
  105.         // qui match la collection du produit actuel
  106.         $associationPetiteTouche $variant->getProduct()->getAssociations()->filter(function ($row) {
  107.             return $row->getType()->getCode() == 'petitetouche';
  108.         })->first();
  109.         $productsPetiteTouche = [];
  110.         if (empty($associationPetiteTouche) == false) {
  111.             $productsPetiteTouche $productVariantRepository->findVariantsByShapeAndColors(
  112.                 $channel,
  113.                 $associationPetiteTouche->getAssociatedProducts()->toArray(),
  114.                 $locale,
  115.                 array_map(function ($row) {
  116.                     return $row->getMatchedProductOptionValue()->getId();
  117.                 }, $matchingColors),
  118.                 // nombre maximum d'éléments
  119.             );
  120.         }
  121.         // Récupération des infos sur "Ca match !" : Couleurs et produits
  122.         $matchingProducts $productVariantRepository->findVariantMatchingColorDifferentShape(
  123.             $channel,
  124.             $variant->getProduct(),
  125.             $locale,
  126.             array_map(function ($row) {
  127.                 return $row->getMatchedProductOptionValue()->getId();
  128.             }, $matchingColors),
  129.             // nombre maximum d'éléments
  130.         );
  131.         // Image de fond pour "Ca match" !
  132.         $siteCollection $em->getRepository(SiteCollection::class)->findOneByProductOptionValue(
  133.             $variant->getOptionValues()->first()
  134.         );
  135.         if (!empty($siteCollection)) {
  136.             $siteCollection->slugLocale SiteCollectionController::CATEGORIES[$localeContext->getLocaleCode()][$siteCollection->getCategory()];
  137.         }
  138.         
  139.         
  140.         if(count($variant->getOptionValues()) > 0){
  141.             // Récupération des infos sur "Produits complémentaires" / "Faites (vous) plaisir !"
  142.             $complementaryProductsSameColor $productVariantRepository->findComplementaryVariantWithSameColor(
  143.                 $channel,
  144.                 $variant,
  145.                 $locale,
  146.                 1000// prix minimum 10€
  147.                 // nombre maximum d'éléments
  148.             );
  149.         }else{
  150.             $complementaryProductsSameColor = array();
  151.         }
  152.         // Récupère un produit tissu s'il existe avec la même couleur
  153.         if(count($variant->getOptionValues()) > 0){  
  154.             // pour l'afficher dans "Produits complémentaires"
  155.             $complementaryFabric $productVariantRepository->findOneFabricForThisProductVariant(
  156.                 $channel,
  157.                 $variant,
  158.                 $locale
  159.             );
  160.         }else{
  161.             $complementaryFabric = array();
  162.         }
  163.         // Récupère la FAQ Produit
  164.         $siteFaqProducts $siteFaqProductRepository->findByVariantAndLocale($variant$locale);
  165.         // Toutes les déclinaisons disponible à afficher en bas
  166.         // Place cette déclinaison à la 3eme position du tableau
  167.         $allVariants array_values($variant->getProduct()->getVariants()->filter(function ($row) {
  168.             return $row->isEnabled() == true;
  169.         })->toArray());
  170.         if (count($allVariants) >= 5) {
  171.             foreach ($allVariants as $index => $row) {
  172.                 if ($index == 2) {
  173.                     $oldVariant $allVariants[$index];
  174.                     $allVariants[$index] = $variant;
  175.                     break;
  176.                 }
  177.             }
  178.             foreach ($allVariants as $index => $row) {
  179.                 if ($index != && $row->getId() == $variant->getId()) {
  180.                     $allVariants[$index] = $oldVariant;
  181.                     break;
  182.                 }
  183.             }
  184.         }
  185.         $produitConfigurateur 0;
  186.         // Fil d'ariane
  187.         $breadcrumbs->prependItem($variant->getName());
  188.         if ($variant->getProduct()->getMainTaxon() != null) {
  189.             $mainTaxon $variant->getProduct()->getMainTaxon();
  190.             // if($mainTaxon->getId() == 172){
  191.             //     $produitConfigurateur = 1; 
  192.             // }
  193.             $taxonParent $mainTaxon;
  194.             while ($taxonParent != $mainTaxon->getRoot()) {
  195.                 $breadcrumbs->prependRouteItem($taxonParent"sylius_shop_product_index", [
  196.                     'slug' => $taxonParent->getSlug()
  197.                 ]);
  198.                 $taxonParent $taxonParent->getParent();
  199.                 // dump($taxonParent->getId());
  200.                 if($taxonParent->getId() == 146){
  201.                     $produitConfigurateur 1
  202.                 }
  203.             }
  204.             $breadcrumbs->prependRouteItem($mainTaxon->getRoot()->getName(), "sylius_shop_product_index", [
  205.                 'slug' => $mainTaxon->getRoot()->getSlug()
  206.             ]);
  207.         }
  208.         $breadcrumbs->prependRouteItem("sylius.ui.home""sylius_shop_homepage");
  209.         //limit de 10 metre pour un tissu
  210.         $meter $variant->countItemStockTissu();
  211.         $tissu 0;
  212.         $carteKdo 0;
  213.         if($variant->getProduct()->getConditioning() == 'per_meter_each_0_5_meter'){
  214.             $tissu 1;
  215.             $cart $cartContext->getCart();
  216.             foreach($cart->getItems() as $cartItem){
  217.               
  218.                 if($cartItem->getVariant()->getId() == $variant->getId()){
  219.                     $meter $meter $cartItem->getConditioningValue();
  220.                 }
  221.             }
  222.            
  223.         }
  224.         else if($variant->getProduct()->getConditioning() == 'card_kdo_per_euros_each_10_euros') {
  225.             $carteKdo 1;
  226.         }
  227.         //si boutique favorite selectionné, on affiche directement le stock de la boutique
  228.         // Récupère toutes les boutiques
  229.         // $shopRepository = $em->getRepository(SiteShop::class);
  230.         // $shops = $shopRepository->findBy([
  231.         //     'enabled' => true
  232.         // ], [
  233.         //     'postalCode' => 'ASC'
  234.         // ]);
  235.         // // Puis récupère leur stock en temps réel
  236.         // $data = $ppmcErpSynchro->retrieveStockPerShopByProductVariantId($variantId);
  237.         // $stockByShop = [];
  238.         // foreach ($data->getStockShop() as $row) {
  239.         //     $stockByShop[$row->getIdShop()] = $row->getStock();
  240.         // }
  241.         $userFavoriteShopStock 0;
  242.         // if(!empty($this->getUser()) && !empty($this->getUser()->getCustomer()) && !empty($this->getUser()->getCustomer()->getFavoriteShop()) && !empty($this->getUser()->getCustomer()->getFavoriteShop()->getId())){
  243.         //     $shopRepository = $em->getRepository(SiteShop::class);
  244.         //     $shop = $shopRepository->find($this->getUser()->getCustomer()->getFavoriteShop()->getId());
  245.             
  246.         //     // Puis récupère leur stock en temps réel
  247.         //     $data = $ppmcErpSynchro->retrieveStockPerShopByProductVariantId((int) $id);
  248.         //     foreach ($data->getStockShop() as $row) {
  249.         //         if($row->getIdShop() ==  $shop->getId()){
  250.         //             $userFavoriteShopStock = 1;
  251.         //         }                
  252.         //     }         
  253.         // }
  254.        
  255.        
  256.         
  257.         return $this->render('site_product_show.html.twig', [
  258.             'produitConfigurateur' => $produitConfigurateur,
  259.             'variant' => $variant,
  260.             'associationAccessoire' => $associationAccessoire,
  261.             'accessoires' => $accessoires,
  262.             'associationPetiteTouche' => $associationPetiteTouche,
  263.             'productsPetiteTouche' => $productsPetiteTouche,
  264.             'siteCollection' => $siteCollection,
  265.             'matchingColors' => $matchingColors,
  266.             'matchingColorsWithPage' => $matchingColorsWithPage,
  267.             'matchingProducts' => $matchingProducts,
  268.             'complementaryProductsSameColor' => $complementaryProductsSameColor,
  269.             'complementaryFabric' => $complementaryFabric,
  270.             'siteFaqProducts' => $siteFaqProducts,
  271.             'allVariants' => $allVariants,
  272.             'meter' => $meter,
  273.             'isTissu' => $tissu,
  274.             'isCarteKdo' => $carteKdo,
  275.             'userFavoriteShopStock' => $userFavoriteShopStock
  276.         ]);
  277.     }
  278.     public function accessoriesAjaxAction(
  279.         Request $request,
  280.         ProductVariantRepositoryInterface $productVariantRepository
  281.     ) {
  282.         $variantId $request->request->get('variantId');
  283.         $accessoryId $request->request->get('accessoryId');
  284.         
  285.         $variant $productVariantRepository->findOneById($variantId);
  286.         if (empty($variant)) {
  287.             throw new NotFoundHttpException("Cette déclinaison produit n'existe pas.");
  288.         }
  289.         $accessory $productVariantRepository->findOneById($accessoryId);
  290.         if (empty($accessory)) {
  291.             throw new NotFoundHttpException("Cet accessoire n'existe pas.");
  292.         }
  293.         $em $this->get('doctrine')->getManager();
  294.         // Récupère toutes les couleurs qui match avec le produit de base
  295.         $matchingColors $em->getRepository(SiteProductOptionValueMatch::class)
  296.         ->findByProductOptionValue($variant->getOptionValues()->first());
  297.         $matchingColorsIds array_map(function ($row) {
  298.             return $row->getMatchedProductOptionValue()->getId();
  299.         }, $matchingColors);
  300.         // Puis récupère toutes les déclinaisons d'accessoires
  301.         $allAccessories $productVariantRepository->findBy([
  302.             'product' => $accessory->getProduct(),
  303.             'enabled' => true
  304.         ]);
  305.         // Ensuite, on affiche dans l'ordre :
  306.         // 1) L'accessoire selectionnée avec cette couleur
  307.         // 2) Les accessoires avec des couleurs qui matchent
  308.         // 3) Le reste des déclinaisons disponibles pour cet accessoire
  309.         $accessories = [];
  310.         $accessoires[] = $accessory;
  311.         foreach ($allAccessories as $index => $row) {
  312.             if ($row->getId() == $accessory->getId()) {
  313.                 unset($allAccessories[$index]);
  314.             } else {
  315.                 foreach ($row->getOptionValues() as $optionValue) {
  316.                     if (in_array($optionValue->getId(), $matchingColorsIds) == true) {
  317.                         $accessoires[] = $row;
  318.                         unset($allAccessories[$index]);
  319.                     }
  320.                 }
  321.             }
  322.         }
  323.         return $this->render('products/accessories_volet.html.twig', [
  324.             'currentAccessoryId' => $accessoryId,
  325.             'product' => $accessory->getProduct(),
  326.             'variant' => $accessory,
  327.             'declinaisons' => $accessoires,
  328.             'more_declinaisons' => $allAccessories
  329.         ]);
  330.     }
  331.     public function sendQuestionProduct(
  332.         Request $request,
  333.         LocaleContextInterface $localeContext,
  334.         ProductVariantRepositoryInterface $productVariantRepository
  335.     ) {
  336.         $question $request->request->get('question'null);
  337.         $variantId $request->request->get('variantId'null);
  338.         // Vérifie si le produit existe
  339.         if (empty($variantId)) {
  340.             return $this->redirectToRoute('sylius_shop_homepage');
  341.         }
  342.         $variant $productVariantRepository->findOneBy([
  343.             'id' => $variantId,
  344.             'enabled' => true
  345.         ]);
  346.         if (empty($variant)) {
  347.             return $this->redirectToRoute('sylius_shop_homepage');
  348.         }
  349.         // Vérifie si la question n'est pas vide
  350.         if (empty(trim($question))) {
  351.             $this->get('session')->getFlashBag()->add('error''La question ne peut pas être vide !');
  352.             return $this->redirectToRoute('app_product_variant_show', [
  353.                 'id' => $variantId,
  354.                 'slug' => $variant->getSlug()
  355.             ]);
  356.         }
  357.         // Vérifie si l'utilisateur est connecté
  358.         if ($this->isGranted('ROLE_USER') == false) {
  359.             $this->get('session')->getFlashBag()->add('error''Vous devez être connecté pour poser une question.');
  360.             return $this->redirectToRoute('app_product_variant_show', [
  361.                 'id' => $variantId,
  362.                 'slug' => $variant->getSlug()
  363.             ]);
  364.         }
  365.         $customer $this->get('security.token_storage')->getToken()->getUser()->getCustomer();
  366.         // Enregistre la question
  367.         $siteFAQProduct = new SiteFAQProduct();
  368.         $siteFAQProduct->setVariant($variant);
  369.         $siteFAQProduct->setCustomer($customer);
  370.         $siteFAQProduct->setLocale($localeContext->getLocaleCode());
  371.         $siteFAQProduct->setQuestion($question);
  372.         $siteFAQProduct->setVisibilityMode('variant');
  373.         $em $this->get('doctrine')->getManager();
  374.         $em->persist($siteFAQProduct);
  375.         $em->flush();
  376.         $this->get('session')->getFlashBag()->add('success''Merci pour votre question, nous y répondrons sous peu.');
  377.         return $this->redirectToRoute('app_product_variant_show', [
  378.             'id' => $variantId,
  379.             'slug' => $variant->getSlug()
  380.         ]);
  381.     }
  382.     public function shopsAjaxAction(
  383.         Request $request,
  384.         ProductVariantRepositoryInterface $productVariantRepository,
  385.         PPMCErpSynchroService $ppmcErpSynchro
  386.     ) {
  387.         
  388.         $variantId intval($request->query->get('variantId'));
  389.       
  390.         $variant $productVariantRepository->findOneById($variantId);
  391.     
  392.         if (empty($variant)) {
  393.             throw new NotFoundHttpException("Cette déclinaison produit n'existe pas.");
  394.         }
  395.         $em $this->get('doctrine')->getManager();
  396.         // Récupère toutes les boutiques
  397.         $shopRepository $em->getRepository(SiteShop::class);
  398.         $shops $shopRepository->findBy([
  399.             'enabled' => true
  400.         ], [
  401.             'postalCode' => 'ASC'
  402.         ]);
  403.         // Puis récupère leur stock en temps réel
  404.         $data $ppmcErpSynchro->retrieveStockPerShopByProductVariantId($variantId);
  405.         $stockByShop = [];
  406.         foreach ($data->getStockShop() as $row) {
  407.             $stockByShop[$row->getIdShop()] = $row->getStock();
  408.         }
  409.     
  410.     
  411.         return $this->render('products/shops_volet.html.twig', [
  412.             'shops' => $shops,
  413.             'stockByShop' => $stockByShop
  414.         ]);
  415.     }
  416.     public function shopsSelectAjaxAction(Request $request)
  417.     {
  418.         
  419.         $idshop intval($request->request->get('idshop'));
  420.         $idstatut intval($request->request->get('idstatut'));
  421.       
  422.         $em $this->get('doctrine')->getManager();
  423.         $shopRepository $em->getRepository(SiteShop::class);
  424.         $shop $shopRepository->findOneById($idshop);
  425.         if (empty($shop) == true) {
  426.             return new Response();
  427.         }
  428.         if ($this->isGranted('ROLE_USER') == true) {
  429.             $repoCustomer $em->getRepository(Customer::class);
  430.             $customer $repoCustomer->findOneBy(['email' => $this->getUser()->getEmail()]);
  431.             $customer->setFavoriteShop($shop);
  432.             $em->persist($customer);
  433.             $em->flush();
  434.         }
  435.         if($idstatut == 0){
  436.             return new Response('Indisponible au magasin : '.$shop->getName());
  437.         }else{
  438.             return new Response('Disponible au magasin : '.$shop->getName());
  439.         }
  440.     }
  441.     public function redirectAction(Request $requestProductVariantRepositoryInterface $productVariantRepository) {
  442.         $forme $request->attributes->get('forme');
  443.         $couleur $request->attributes->get('couleur');
  444.         // $session = $request->getSession();
  445.         // dump($session);
  446.         // exit();
  447.         
  448.         $variant $productVariantRepository->findOneBy([
  449.             'oldUrl' => $forme.'/'.$couleur
  450.         ]);
  451.         if(!empty($variant)) {
  452.             return $this->redirectToRoute('app_product_variant_show', [
  453.                 'slug' => $variant->getSlug(),
  454.                 'id' => $variant->getId()
  455.             ], 301);
  456.         }
  457.         else {
  458.             throw new NotFoundHttpException("Cette déclinaison produit n'existe pas.");
  459.         }
  460.     }
  461.     public function redirectActionDirectId(Request $requestProductVariantRepositoryInterface $productVariantRepository) {
  462.         $id $request->attributes->get('id');
  463.         
  464.         $variant $productVariantRepository->findOneBy([
  465.             'id' => $id
  466.         ]);
  467.         if(!empty($variant)) {
  468.             return $this->redirectToRoute('app_product_variant_show', [
  469.                 'slug' => $variant->getSlug(),
  470.                 'id' => $variant->getId()
  471.             ], 301);
  472.         }
  473.         else {
  474.             throw new NotFoundHttpException("Cette déclinaison produit n'existe pas.");
  475.         }
  476.     }
  477. }