<?php
declare(strict_types=1);
namespace App\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Sylius\Component\Locale\Context\LocaleContextInterface;
use Sylius\Component\Channel\Context\ChannelContextInterface;
use Sylius\Component\Core\Repository\ProductVariantRepositoryInterface;
use Sylius\Component\Taxonomy\Repository\TaxonRepositoryInterface;
use Sylius\Bundle\CoreBundle\Form\Type\Order\AddToCartType;
use WhiteOctober\BreadcrumbsBundle\Model\Breadcrumbs;
use App\Services\PPMCErpSynchroService;
use App\Doctrine\ORM\SiteFAQProductRepository;
use App\Entity\Customer\Customer;
use App\Entity\SiteProductOptionValueMatch;
use App\Entity\SiteFAQProduct;
use App\Entity\SiteShop;
use App\Entity\SiteCollection;
use Sylius\Component\Order\Context\CartContextInterface;
use App\Controller\SiteCollectionController;
class ProductController extends AbstractController
{
public function showAction(
Request $request,
ChannelContextInterface $channelContext,
LocaleContextInterface $localeContext,
ProductVariantRepositoryInterface $productVariantRepository,
TaxonRepositoryInterface $taxonRepository,
SiteFAQProductRepository $siteFaqProductRepository,
Breadcrumbs $breadcrumbs,
CartContextInterface $cartContext,
PPMCErpSynchroService $ppmcErpSynchro,
$slug,
$id
) {
$channel = $channelContext->getChannel();
$locale = $localeContext->getLocaleCode();
// Récupère la déclinaison produit
$variant = $productVariantRepository->findOneById($id);
// if($_SERVER['REMOTE_ADDR'] == '91.168.137.186') {
// dump($variant);
// exit();
// }
if (empty($variant)) {
throw new NotFoundHttpException("Cette déclinaison produit n'existe pas.");
}
$isAdmin = intval($request->query->get('admin'));
if ($variant->isEnabled() == false && $isAdmin == 0) {
throw new NotFoundHttpException("Cette déclinaison produit est désactivée.");
}
// Vérifie si le produit parent appartient à ce canal
if ($variant->getProduct()->hasChannel($channel) == false) {
throw new NotFoundHttpException("Cette déclinaison produit n'appartient pas à ce canal.");
}
if ($slug != $variant->getSlug()) {
return $this->redirectToRoute('app_product_variant_show', [
'slug' => $variant->getSlug(),
'id' => $variant->getId()
]);
}
// Ajoute la déclinaison dans les "produits déjà vu"
$lastViewedProductVariantsIds = $this->get('session')->get('lastViewedProductVariantsIds', []);
// FIXME parameter au lieu de "16" + passer ce parameter a twig
if (count($lastViewedProductVariantsIds) >= 16) {
array_shift($lastViewedProductVariantsIds);
}
array_push($lastViewedProductVariantsIds, $variant->getId());
$this->get('session')->set('lastViewedProductVariantsIds', $lastViewedProductVariantsIds);
// Récupère les collections qui match (couleurs associées)
$em = $this->get('doctrine')->getManager();
$matchingColors = $em->getRepository(SiteProductOptionValueMatch::class)
->findByProductOptionValue($variant->getOptionValues()->first());
shuffle($matchingColors);
// Récupère les collections qui match et qui
// possède une page "collection" sur le site
$matchingColorsWithPage = $em->getRepository(SiteCollection::class)
->findByProductOptionValue(array_map(function ($row) {
return $row->getMatchedProductOptionValue();
}, $matchingColors));
// Récupération des accessoires
$associationAccessoire = $variant->getProduct()->getAssociations()->filter(function ($row) {
return $row->getType()->getCode() == 'accessoire';
})->first();
$accessoires = [];
if (empty($associationAccessoire) == false) {
$accessoires = $productVariantRepository->findVariantsByShapeAndColors(
$channel,
$associationAccessoire->getAssociatedProducts()->toArray(),
$locale,
array_map(function ($row) {
if($row->getMatchedProductOptionValue()){
return $row->getMatchedProductOptionValue()->getId();
}
return;
}, $matchingColors),
6 // nombre maximum d'éléments
);
}
// Récupération des produits associés à "J'ajoute ma petite touche"
// puis récupère des déclinaisons qui correspondent à des collections
// qui match la collection du produit actuel
$associationPetiteTouche = $variant->getProduct()->getAssociations()->filter(function ($row) {
return $row->getType()->getCode() == 'petitetouche';
})->first();
$productsPetiteTouche = [];
if (empty($associationPetiteTouche) == false) {
$productsPetiteTouche = $productVariantRepository->findVariantsByShapeAndColors(
$channel,
$associationPetiteTouche->getAssociatedProducts()->toArray(),
$locale,
array_map(function ($row) {
return $row->getMatchedProductOptionValue()->getId();
}, $matchingColors),
6 // nombre maximum d'éléments
);
}
// Récupération des infos sur "Ca match !" : Couleurs et produits
$matchingProducts = $productVariantRepository->findVariantMatchingColorDifferentShape(
$channel,
$variant->getProduct(),
$locale,
array_map(function ($row) {
return $row->getMatchedProductOptionValue()->getId();
}, $matchingColors),
6 // nombre maximum d'éléments
);
// Image de fond pour "Ca match" !
$siteCollection = $em->getRepository(SiteCollection::class)->findOneByProductOptionValue(
$variant->getOptionValues()->first()
);
if (!empty($siteCollection)) {
$siteCollection->slugLocale = SiteCollectionController::CATEGORIES[$localeContext->getLocaleCode()][$siteCollection->getCategory()];
}
if(count($variant->getOptionValues()) > 0){
// Récupération des infos sur "Produits complémentaires" / "Faites (vous) plaisir !"
$complementaryProductsSameColor = $productVariantRepository->findComplementaryVariantWithSameColor(
$channel,
$variant,
$locale,
1000, // prix minimum 10€
6 // nombre maximum d'éléments
);
}else{
$complementaryProductsSameColor = array();
}
// Récupère un produit tissu s'il existe avec la même couleur
if(count($variant->getOptionValues()) > 0){
// pour l'afficher dans "Produits complémentaires"
$complementaryFabric = $productVariantRepository->findOneFabricForThisProductVariant(
$channel,
$variant,
$locale
);
}else{
$complementaryFabric = array();
}
// Récupère la FAQ Produit
$siteFaqProducts = $siteFaqProductRepository->findByVariantAndLocale($variant, $locale);
// Toutes les déclinaisons disponible à afficher en bas
// Place cette déclinaison à la 3eme position du tableau
$allVariants = array_values($variant->getProduct()->getVariants()->filter(function ($row) {
return $row->isEnabled() == true;
})->toArray());
if (count($allVariants) >= 5) {
foreach ($allVariants as $index => $row) {
if ($index == 2) {
$oldVariant = $allVariants[$index];
$allVariants[$index] = $variant;
break;
}
}
foreach ($allVariants as $index => $row) {
if ($index != 2 && $row->getId() == $variant->getId()) {
$allVariants[$index] = $oldVariant;
break;
}
}
}
$produitConfigurateur = 0;
// Fil d'ariane
$breadcrumbs->prependItem($variant->getName());
if ($variant->getProduct()->getMainTaxon() != null) {
$mainTaxon = $variant->getProduct()->getMainTaxon();
// if($mainTaxon->getId() == 172){
// $produitConfigurateur = 1;
// }
$taxonParent = $mainTaxon;
while ($taxonParent != $mainTaxon->getRoot()) {
$breadcrumbs->prependRouteItem($taxonParent, "sylius_shop_product_index", [
'slug' => $taxonParent->getSlug()
]);
$taxonParent = $taxonParent->getParent();
// dump($taxonParent->getId());
if($taxonParent->getId() == 146){
$produitConfigurateur = 1;
}
}
$breadcrumbs->prependRouteItem($mainTaxon->getRoot()->getName(), "sylius_shop_product_index", [
'slug' => $mainTaxon->getRoot()->getSlug()
]);
}
$breadcrumbs->prependRouteItem("sylius.ui.home", "sylius_shop_homepage");
//limit de 10 metre pour un tissu
$meter = $variant->countItemStockTissu();
$tissu = 0;
$carteKdo = 0;
if($variant->getProduct()->getConditioning() == 'per_meter_each_0_5_meter'){
$tissu = 1;
$cart = $cartContext->getCart();
foreach($cart->getItems() as $cartItem){
if($cartItem->getVariant()->getId() == $variant->getId()){
$meter = $meter - $cartItem->getConditioningValue();
}
}
}
else if($variant->getProduct()->getConditioning() == 'card_kdo_per_euros_each_10_euros') {
$carteKdo = 1;
}
//si boutique favorite selectionné, on affiche directement le stock de la boutique
// Récupère toutes les boutiques
// $shopRepository = $em->getRepository(SiteShop::class);
// $shops = $shopRepository->findBy([
// 'enabled' => true
// ], [
// 'postalCode' => 'ASC'
// ]);
// // Puis récupère leur stock en temps réel
// $data = $ppmcErpSynchro->retrieveStockPerShopByProductVariantId($variantId);
// $stockByShop = [];
// foreach ($data->getStockShop() as $row) {
// $stockByShop[$row->getIdShop()] = $row->getStock();
// }
$userFavoriteShopStock = 0;
// if(!empty($this->getUser()) && !empty($this->getUser()->getCustomer()) && !empty($this->getUser()->getCustomer()->getFavoriteShop()) && !empty($this->getUser()->getCustomer()->getFavoriteShop()->getId())){
// $shopRepository = $em->getRepository(SiteShop::class);
// $shop = $shopRepository->find($this->getUser()->getCustomer()->getFavoriteShop()->getId());
// // Puis récupère leur stock en temps réel
// $data = $ppmcErpSynchro->retrieveStockPerShopByProductVariantId((int) $id);
// foreach ($data->getStockShop() as $row) {
// if($row->getIdShop() == $shop->getId()){
// $userFavoriteShopStock = 1;
// }
// }
// }
return $this->render('site_product_show.html.twig', [
'produitConfigurateur' => $produitConfigurateur,
'variant' => $variant,
'associationAccessoire' => $associationAccessoire,
'accessoires' => $accessoires,
'associationPetiteTouche' => $associationPetiteTouche,
'productsPetiteTouche' => $productsPetiteTouche,
'siteCollection' => $siteCollection,
'matchingColors' => $matchingColors,
'matchingColorsWithPage' => $matchingColorsWithPage,
'matchingProducts' => $matchingProducts,
'complementaryProductsSameColor' => $complementaryProductsSameColor,
'complementaryFabric' => $complementaryFabric,
'siteFaqProducts' => $siteFaqProducts,
'allVariants' => $allVariants,
'meter' => $meter,
'isTissu' => $tissu,
'isCarteKdo' => $carteKdo,
'userFavoriteShopStock' => $userFavoriteShopStock
]);
}
public function accessoriesAjaxAction(
Request $request,
ProductVariantRepositoryInterface $productVariantRepository
) {
$variantId = $request->request->get('variantId');
$accessoryId = $request->request->get('accessoryId');
$variant = $productVariantRepository->findOneById($variantId);
if (empty($variant)) {
throw new NotFoundHttpException("Cette déclinaison produit n'existe pas.");
}
$accessory = $productVariantRepository->findOneById($accessoryId);
if (empty($accessory)) {
throw new NotFoundHttpException("Cet accessoire n'existe pas.");
}
$em = $this->get('doctrine')->getManager();
// Récupère toutes les couleurs qui match avec le produit de base
$matchingColors = $em->getRepository(SiteProductOptionValueMatch::class)
->findByProductOptionValue($variant->getOptionValues()->first());
$matchingColorsIds = array_map(function ($row) {
return $row->getMatchedProductOptionValue()->getId();
}, $matchingColors);
// Puis récupère toutes les déclinaisons d'accessoires
$allAccessories = $productVariantRepository->findBy([
'product' => $accessory->getProduct(),
'enabled' => true
]);
// Ensuite, on affiche dans l'ordre :
// 1) L'accessoire selectionnée avec cette couleur
// 2) Les accessoires avec des couleurs qui matchent
// 3) Le reste des déclinaisons disponibles pour cet accessoire
$accessories = [];
$accessoires[] = $accessory;
foreach ($allAccessories as $index => $row) {
if ($row->getId() == $accessory->getId()) {
unset($allAccessories[$index]);
} else {
foreach ($row->getOptionValues() as $optionValue) {
if (in_array($optionValue->getId(), $matchingColorsIds) == true) {
$accessoires[] = $row;
unset($allAccessories[$index]);
}
}
}
}
return $this->render('products/accessories_volet.html.twig', [
'currentAccessoryId' => $accessoryId,
'product' => $accessory->getProduct(),
'variant' => $accessory,
'declinaisons' => $accessoires,
'more_declinaisons' => $allAccessories
]);
}
public function sendQuestionProduct(
Request $request,
LocaleContextInterface $localeContext,
ProductVariantRepositoryInterface $productVariantRepository
) {
$question = $request->request->get('question', null);
$variantId = $request->request->get('variantId', null);
// Vérifie si le produit existe
if (empty($variantId)) {
return $this->redirectToRoute('sylius_shop_homepage');
}
$variant = $productVariantRepository->findOneBy([
'id' => $variantId,
'enabled' => true
]);
if (empty($variant)) {
return $this->redirectToRoute('sylius_shop_homepage');
}
// Vérifie si la question n'est pas vide
if (empty(trim($question))) {
$this->get('session')->getFlashBag()->add('error', 'La question ne peut pas être vide !');
return $this->redirectToRoute('app_product_variant_show', [
'id' => $variantId,
'slug' => $variant->getSlug()
]);
}
// Vérifie si l'utilisateur est connecté
if ($this->isGranted('ROLE_USER') == false) {
$this->get('session')->getFlashBag()->add('error', 'Vous devez être connecté pour poser une question.');
return $this->redirectToRoute('app_product_variant_show', [
'id' => $variantId,
'slug' => $variant->getSlug()
]);
}
$customer = $this->get('security.token_storage')->getToken()->getUser()->getCustomer();
// Enregistre la question
$siteFAQProduct = new SiteFAQProduct();
$siteFAQProduct->setVariant($variant);
$siteFAQProduct->setCustomer($customer);
$siteFAQProduct->setLocale($localeContext->getLocaleCode());
$siteFAQProduct->setQuestion($question);
$siteFAQProduct->setVisibilityMode('variant');
$em = $this->get('doctrine')->getManager();
$em->persist($siteFAQProduct);
$em->flush();
$this->get('session')->getFlashBag()->add('success', 'Merci pour votre question, nous y répondrons sous peu.');
return $this->redirectToRoute('app_product_variant_show', [
'id' => $variantId,
'slug' => $variant->getSlug()
]);
}
public function shopsAjaxAction(
Request $request,
ProductVariantRepositoryInterface $productVariantRepository,
PPMCErpSynchroService $ppmcErpSynchro
) {
$variantId = intval($request->query->get('variantId'));
$variant = $productVariantRepository->findOneById($variantId);
if (empty($variant)) {
throw new NotFoundHttpException("Cette déclinaison produit n'existe pas.");
}
$em = $this->get('doctrine')->getManager();
// Récupère toutes les boutiques
$shopRepository = $em->getRepository(SiteShop::class);
$shops = $shopRepository->findBy([
'enabled' => true
], [
'postalCode' => 'ASC'
]);
// Puis récupère leur stock en temps réel
$data = $ppmcErpSynchro->retrieveStockPerShopByProductVariantId($variantId);
$stockByShop = [];
foreach ($data->getStockShop() as $row) {
$stockByShop[$row->getIdShop()] = $row->getStock();
}
return $this->render('products/shops_volet.html.twig', [
'shops' => $shops,
'stockByShop' => $stockByShop
]);
}
public function shopsSelectAjaxAction(Request $request)
{
$idshop = intval($request->request->get('idshop'));
$idstatut = intval($request->request->get('idstatut'));
$em = $this->get('doctrine')->getManager();
$shopRepository = $em->getRepository(SiteShop::class);
$shop = $shopRepository->findOneById($idshop);
if (empty($shop) == true) {
return new Response();
}
if ($this->isGranted('ROLE_USER') == true) {
$repoCustomer = $em->getRepository(Customer::class);
$customer = $repoCustomer->findOneBy(['email' => $this->getUser()->getEmail()]);
$customer->setFavoriteShop($shop);
$em->persist($customer);
$em->flush();
}
if($idstatut == 0){
return new Response('Indisponible au magasin : '.$shop->getName());
}else{
return new Response('Disponible au magasin : '.$shop->getName());
}
}
public function redirectAction(Request $request, ProductVariantRepositoryInterface $productVariantRepository) {
$forme = $request->attributes->get('forme');
$couleur = $request->attributes->get('couleur');
// $session = $request->getSession();
// dump($session);
// exit();
$variant = $productVariantRepository->findOneBy([
'oldUrl' => $forme.'/'.$couleur
]);
if(!empty($variant)) {
return $this->redirectToRoute('app_product_variant_show', [
'slug' => $variant->getSlug(),
'id' => $variant->getId()
], 301);
}
else {
throw new NotFoundHttpException("Cette déclinaison produit n'existe pas.");
}
}
public function redirectActionDirectId(Request $request, ProductVariantRepositoryInterface $productVariantRepository) {
$id = $request->attributes->get('id');
$variant = $productVariantRepository->findOneBy([
'id' => $id
]);
if(!empty($variant)) {
return $this->redirectToRoute('app_product_variant_show', [
'slug' => $variant->getSlug(),
'id' => $variant->getId()
], 301);
}
else {
throw new NotFoundHttpException("Cette déclinaison produit n'existe pas.");
}
}
}