src/Utils/AddToCart.php line 267

Open in your IDE?
  1. <?php
  2. namespace App\Utils;
  3. use App\Entity\Gos\Cart;
  4. use App\Entity\Gos\Country;
  5. use App\Entity\Gos\Coupon;
  6. use App\Entity\Gos\PaymentMethod;
  7. use App\Entity\Gos\PortalSettings;
  8. use App\Entity\Gos\ProductAssociation;
  9. use App\Entity\Gos\ProductCart;
  10. use App\Entity\Gos\ProductPack;
  11. use App\Entity\Gos\ProductPackItem;
  12. use App\Entity\Gos\ProductVariant;
  13. use App\Entity\Gos\Uniqskills\Course;
  14. use App\Entity\Gos\User;
  15. use App\Enum\UpsellingTypes;
  16. use App\Utils\Cart\CartPriceCalculator;
  17. use App\Utils\FacebookPixel\Api\FacebookPixelService;
  18. use App\Utils\Region\CountryService;
  19. use Doctrine\ORM\EntityManagerInterface;
  20. use Symfony\Component\HttpFoundation\Cookie;
  21. use Symfony\Component\HttpFoundation\Request;
  22. use Symfony\Component\HttpFoundation\RequestStack;
  23. use Symfony\Component\HttpFoundation\Response;
  24. use Symfony\Component\Security\Core\Security;
  25. use Symfony\Contracts\Translation\TranslatorInterface;
  26. class AddToCart
  27. {
  28.     private ?Request $request;
  29.     private EntityManagerInterface $em;
  30.     private CartServices $cartServices;
  31.     private TranslatorInterface $translator;
  32.     private CountryService $countryService;
  33.     private FacebookPixelService $facebookPixelService;
  34.     private PortalSettingsService $portalSettingsService;
  35.     private CouponClass $couponClass;
  36.     private $paymentMethod;
  37.     private $portalSettings;
  38.     private $cart null;
  39.     private $user;
  40.     private $productsForGA = [];
  41.     private $status  false;
  42.     private $message false;
  43.     private CartPriceCalculator $cartPriceCalculator;
  44.     public function __construct(
  45.         RequestStack $requestStack,
  46.         EntityManagerInterface $entityManager,
  47.         Security $security,
  48.         CartServices $cartServices,
  49.         TranslatorInterface $translator,
  50.         CountryService $countryService,
  51.         FacebookPixelService $facebookPixelService,
  52.         PortalSettingsService $portalSettingsService,
  53.         CouponClass $couponClass,
  54.         CartPriceCalculator $cartPriceCalculator
  55.     ) {
  56.         $this->request               $requestStack->getCurrentRequest();
  57.         $this->em                    $entityManager;
  58.         $this->user                  $security->getUser();
  59.         $this->cartServices          $cartServices;
  60.         $this->translator            $translator;
  61.         $this->countryService        $countryService;
  62.         $this->facebookPixelService  $facebookPixelService;
  63.         $this->portalSettingsService $portalSettingsService;
  64.         $this->couponClass           $couponClass;
  65.         $this->cartPriceCalculator   $cartPriceCalculator;
  66.         $this->findPortalSettings();
  67.         $this->findCart();
  68.         $this->findPaymentMethod();
  69.     }
  70.     public function addVoucherToCart($voucherCode)
  71.     {
  72.         $voucherCoupon $this->em->getRepository(Coupon::class)->findVoucherCode($voucherCode);
  73.         $voucherVariant $voucherCoupon->getGift()->getOrderProductVariant()->getProductVariant()->getProductVariantNoComplete();
  74.         if ($this->request === null)
  75.         {
  76.             return false;
  77.         }
  78.         $this->request->request->set('productVariantNoComplete'$voucherVariant);
  79.         $this->request->request->set('coupon'$voucherCoupon->getCode());
  80.         $this->request->request->set('returnCart'true);
  81.         return $this->addToCart();
  82.     }
  83.     public function addToCart($user nullstring $productVariantNo null)
  84.     {
  85.         $this->user $user;
  86.         $repoPC     $this->em->getRepository(ProductCart::class);
  87.         if ($this->request->get('clearCart'))
  88.         {
  89.             /** @var ProductCart $productCart */
  90.             foreach ($this->cart->getProductCart() as $productCart)
  91.             {
  92.                 $this->cartServices->removeProductFromCart($user$productCart->getId());
  93.             }
  94.             $this->em->flush();
  95.             $this->em->refresh($this->cart);
  96.         }
  97.         if (
  98.             $this->request->get('portalHash')
  99.             || (
  100.                 $this->cart->getPortalSettings() === null
  101.                 && $this->request->getSession()->has('portalSettingsHash')
  102.             )
  103.         )
  104.         {
  105.             $this->findPortalSettings();
  106.             if ($this->portalSettings)
  107.             {
  108.                 $this->cart->setPortalSettings($this->portalSettings);
  109.             }
  110.             $this->em->flush();
  111.             $this->em->refresh($this->cart);
  112.         }
  113.         $newProductVariant $this->findProductVariantToAdd($productVariantNo);
  114.         $newProductPack    $this->findProductPackToAdd();
  115.         if (empty($newProductVariant) && empty($newProductPack))
  116.         {
  117.             $this->addCoupon(); // Add coupon to existing products in cart anyway
  118.             return ['error' => 'Product not found'];
  119.         }
  120.         if (isset($newProductVariant['error']))
  121.         {
  122.             return $newProductVariant;
  123.         }
  124.         $this->addToCartProductPack($newProductPack);
  125.         $this->addToCartProductVariant($newProductVariant);
  126.         $this->addCoupon();
  127.         if ($this->request->request->get('returnCart'false))
  128.         {
  129.             return array(
  130.                 'status'   => $this->status,
  131.                 'redirect' => 1
  132.             );
  133.         }
  134.         $price $this->cartPriceCalculator->getCartPrice($this->cart); // return price with postage cost
  135.         foreach ($this->productsForGA as $key => $product)
  136.         {
  137.             $this->productsForGA[$key]['price'] = $price[$product['ppiId'] ?? $product['pvId']]->totalPriceAfterCouponGross;
  138.         }
  139.         return [
  140.             'quantity'       => $repoPC->sumProductCart($this->cart->getHash()),
  141.             'cartTotalPrice' => $price['totalPriceAfterCouponGross'],
  142.             'message'        => $this->message,
  143.             'status'         => $this->status,
  144.             'products'       => $this->productsForGA
  145.         ];
  146.     }
  147.     public function getHash(): string
  148.     {
  149.         return $this->cart->getHash();
  150.     }
  151.     private function findProductVariantToAdd(?string $productVariantNo)
  152.     {
  153.         $newProductVariant        = array();
  154.         $productVariantNoComplete $productVariantNo ?: $this->request->get('productVariantNoComplete');
  155.         if (!empty($productVariantNoComplete))
  156.         {
  157.             $arrayProductVariantNo  explode(','$productVariantNoComplete);
  158.             $newProductVariant      $this->em->getRepository(ProductVariant::class)
  159.                 ->findProductVariantToAdd($arrayProductVariantNo);
  160.             $newProductVariant $this->replaceBaseVariantsWithTargetVariants($newProductVariant); //zabezpieczenie: jeżeli wariant docelowy jest ustawiony, to dodajemy do koszyka wariant docelowy, a nie wariant z linku (FO —> BC)
  161.             if (!empty($newProductVariant)
  162.                 && ($this->request->request->get('source') == 'uniqskills'
  163.                 || $this->request->query->get('source') == 'uniqskills'))
  164.             {
  165.                 foreach ($newProductVariant as $npv)
  166.                 {
  167.                     $this->facebookPixelService
  168.                         ->setEvent('AddToCart'$npv->getId())
  169.                         ->request();
  170.                     /** @var $npv ProductVariant */
  171.                     $userCountry $this->countryService->getCountry($this->request$this->user);
  172.                     $exploded explode('/'parse_url($this->request->headers->get('referer'), PHP_URL_PATH));
  173.                     $isInCart end($exploded) === 'cart';
  174.                     if (((empty($npv->getCountry()) && $userCountry && $userCountry->getAlpha2() != 'PL')
  175.                         || $userCountry != $npv->getCountry()) && !$isInCart)
  176.                     {
  177.                         return [
  178.                             'status'    => false,
  179.                             'error'     => 'wrongCountry',
  180.                             'message'   => $this->translator->trans(
  181.                                 'errors.order.wrongCountry',
  182.                                 [],
  183.                                 'messages',
  184.                                 $this->request->getSession()->get('userLocale''pl')
  185.                             )
  186.                         ];
  187.                     }
  188.                 }
  189.             }
  190.             $portal $this->portalSettingsService->getPortalSettings();
  191.             if ($portal && $portal->getUseFbPixelInIframe() === true)
  192.             {
  193.                 foreach ($newProductVariant as $npv)
  194.                 {
  195.                     $this->facebookPixelService
  196.                         ->setEvent('AddToCart'$npv->getId())
  197.                         ->request();
  198.                 }
  199.             }
  200.         }
  201.         return $newProductVariant;
  202.     }
  203.     private function findProductPackToAdd()
  204.     {
  205.         $newProductPack = array();
  206.         $productPackId  $this->request->get('productPackId');
  207.         if (!empty($productPackId))
  208.         {
  209.             $arrayProductPackId explode(','$productPackId);
  210.             $newProductPack     $this->em->getRepository(ProductPack::class)
  211.                 ->findProductPackToAdd($arrayProductPackId);
  212.         }
  213.         return $newProductPack;
  214.     }
  215.     private function findCart()
  216.     {
  217.         $cartHash $this->getCartHash();
  218.         if (!empty($cartHash))
  219.         {
  220.             $this->cart $this->em->getRepository(Cart::class)->findOneByHash($cartHash);
  221.         }
  222.         if (empty($this->cart))
  223.         {
  224.             $this->cart $this->cartServices->createCart($this->user instanceof User $this->user false);
  225.         }
  226.         $this->request->getSession()->set('cartHash'$this->cart->getHash());
  227.     }
  228.     private function findPortalSettings()
  229.     {
  230.         $hash                 $this->request->getSession()->get('portalSettingsHash');
  231.         $this->portalSettings $this->em->getRepository(PortalSettings::class)->findOneByHash($hash);
  232.     }
  233.     private function findPaymentMethod()
  234.     {
  235.         $this->paymentMethod $this->em->getRepository(PaymentMethod::class)->findOneBySlug('invoice');
  236.     }
  237.     private function getCartHash()
  238.     {
  239.         if ($this->user instanceof User && $this->user->getCart())
  240.         {
  241.             return $this->user->getCart()->getHash();
  242.         }
  243.         if ($this->request->getSession()->has('cartHash'))
  244.         {
  245.             return $this->request->getSession()->get('cartHash');
  246.         }
  247.         return $this->request->cookies->get('cartHash'$this->request->get('cartHash'));
  248.     }
  249.     /**
  250.      * Add coupon
  251.      */
  252.     public function addCoupon($couponCode null)
  253.     {
  254.         if (!$couponCode)
  255.         {
  256.             $couponCode $this->request->request->get('coupon'$this->request->query->get('coupon'false));
  257.         }
  258.         if ($couponCode)
  259.         {
  260.             $couponCodes explode('|'$couponCode);
  261.             foreach ($couponCodes as $code)
  262.             {
  263.                 $coupon      $this->couponClass->add($this->cart$code);
  264.                 $this->em->refresh($this->cart);
  265.                 if (isset($coupon['message']))
  266.                 {
  267.                     $this->request->getSession()->getFlashBag()->add('warningCart'$coupon['message']);
  268.                 }
  269.             }
  270.         }
  271.     }
  272.     private function createProductCart(ProductVariant $productVariant null$productPack null$additionalUpselling false)
  273.     {
  274.         $productCart = (new ProductCart())
  275.             ->setPaymentMethod($this->paymentMethod)
  276.             ->setQuantity(1)
  277.             ->setCart($this->cart);
  278.         if ($additionalUpselling === true$productCart->setUpsellingType(UpsellingTypes::FORCED);
  279.         if ($productVariant)
  280.         {
  281.             $productCart->setProductVariant($productVariant);
  282.             if ($productPack)
  283.             {
  284.                 $productCart->setCycleProductPack($productPack);
  285.             }
  286.         }
  287.         elseif ($productPack)
  288.         {
  289.             $productCart->setProductPack($productPack);
  290.         }
  291.         $countClients $this->request->request->get('countClients'false);
  292.         if ($countClients && $countClients 1)
  293.         {
  294.             $productCart->setQuantity($countClients);
  295.         }
  296.         $this->couponClass->assignCouponsToProductCart($productCart);
  297.         return $productCart;
  298.     }
  299.     public function addToCartProductVariant($newProductVariant$additionalUpselling false): void
  300.     {
  301.         $repoPC $this->em->getRepository(ProductCart::class);
  302.         $isGift $this->request->get('gift'false);
  303.         foreach ($newProductVariant as $newPV)
  304.         {
  305.             /** @var ProductCart $productCart */
  306.             $productCart $repoPC->findCartOnProductVariant($this->cart->getHash(), $newPV->getId());
  307.             if ($productCart and $additionalUpselling === true) continue;
  308.             /** @var ProductVariant $newPV */
  309.             if ($newPV->isSaleDisabled())
  310.             {
  311.                 $this->message $this->translator->trans(
  312.                     'errors.order.saleDisabled',
  313.                     [],
  314.                     'messages',
  315.                     $this->request->getSession()->get('userLocale''pl')
  316.                 );
  317.                 if ($productCart)
  318.                 {
  319.                     $this->cart->removeProductCart($productCart);
  320.                     $this->em->persist($productCart);
  321.                     $this->em->flush();
  322.                 }
  323.                 return;
  324.             }
  325.             /** @var ProductVariant $newPV */
  326.             if ($newPV->isActive())
  327.             {
  328.                 if ($productCart)
  329.                 {
  330.                     $quantity $productCart->getQuantity();
  331.                     if ($productCart->hasUniqskillsMultiUserCourse()
  332.                         && $quantity === $productCart->getProductVariant()->getMaxUsers())
  333.                     {
  334.                         $this->status true;
  335.                         return;
  336.                     }
  337.                     else
  338.                         $productCart->setQuantity($newPV->getBuyMaxOne() ? : ++$quantity);
  339.                 }
  340.                 else
  341.                 {
  342.                     if ($this->checkIfProductIsCorrectCountry($newPV))
  343.                     {
  344.                         $this->setCountryToCart($newPV);
  345.                         $productCart $this->createProductCart($newPVnull$additionalUpselling);
  346.                     }
  347.                     else
  348.                     {
  349.                         $this->message $this->translator->trans(
  350.                             'errors.order.wrongCountry',
  351.                             [],
  352.                             'messages',
  353.                             $this->request->getSession()->get('userLocale''pl')
  354.                         );
  355.                         if ($productCart)
  356.                         {
  357.                             $this->cart->removeProductCart($productCart);
  358.                             $this->em->persist($productCart);
  359.                             $this->em->flush();
  360.                         }
  361.                         return;
  362.                     }
  363.                 }
  364.                 if ($isGift)
  365.                 {
  366.                     $productCart->setIsGift(true);
  367.                 }
  368.                 if ($this->request->request->get('productAssociationId'))
  369.                 {
  370.                     $productAssociationId $this->request->request->get('productAssociationId');
  371.                     $productAssociation $this->em->getRepository(ProductAssociation::class)->find($productAssociationId);
  372.                     if ($productAssociation)
  373.                     {
  374.                         $productCart->setProductAssociation($productAssociation);
  375.                     }
  376.                 }
  377.                 if ($this->request->get('source') == 'uniqskills')
  378.                 {
  379.                     $productCart->setLifetimeLanding($this->request->get('lifetimeLanding'false));
  380.                     $courseSlug $this->request->get('courseSlug');
  381.                     $course $this->em->getRepository(Course::class)->findOneBySlug($courseSlug);
  382.                     if (!is_null($course)) $productCart->setCourse($course);
  383.                 }
  384.                 $upsellingType = (int)$this->request->get('upsellingType');
  385.                 if ($upsellingType && UpsellingTypes::isValidValue($upsellingType))
  386.                 {
  387.                     $productCart->setUpsellingType($upsellingType);
  388.                 }
  389.                 if (
  390.                     $this->request->get('parentProductCart')
  391.                     &&
  392.                     $parentProductCart $repoPC->find($this->request->get('parentProductCart'))
  393.                 )
  394.                 {
  395.                     $productCart->setParent($parentProductCart);
  396.                     $productCart->setQuantity($parentProductCart->getQuantity());
  397.                 }
  398.                 $this->em->persist($this->cart);
  399.                 $this->em->persist($productCart);
  400.                 $this->em->flush();
  401.                 $this->em->refresh($this->cart);
  402.                 $productVariant $productCart->getProductVariant();
  403.                 $this->productsForGA[] = array(
  404.                     'pvId'                      => $productVariant->getId(),
  405.                     'productVariantNoComplete'  => $productVariant->getProductVariantNoComplete(),
  406.                     'tradeName'                 => $productVariant->getTradeName(),
  407.                     'price'                     => 0,
  408.                     'brand'                     => $productVariant->getMasterProduct()->getProductGroups() ? $productVariant->getMasterProduct()->getProductGroups()->getName() : '',
  409.                     'category'                  => $productVariant->getMasterProduct()->getProductType() ? $productVariant->getMasterProduct()->getProductType()->getName() : '',
  410.                     'quantity'                  => $productCart->getQuantity(),
  411.                     'coupon'                    => $productCart->getCoupon() ? $productCart->getCoupon()->getCode() : null
  412.                 );
  413.                 $this->status  true;
  414.             }
  415.             else
  416.             {
  417.                 $this->message $this->translator->trans(
  418.                     'errors.order.notAvailable',
  419.                     [],
  420.                     'messages',
  421.                     $this->request->getSession()->get('userLocale''pl')
  422.                 );
  423.                 if ($productCart)
  424.                 {
  425.                     $this->cart->removeProductCart($productCart);
  426.                     $this->em->persist($productCart);
  427.                     $this->em->flush();
  428.                 }
  429.             }
  430.         }
  431.     }
  432.     public function setButtonParameterCookie(Response $response): void
  433.     {
  434.         if ($this->request && $this->request->request->get('bp'))
  435.         {
  436.             $bp $this->request->cookies->get('bp', array());
  437.             if (!empty($bp))
  438.             {
  439.                 $bp json_decode($bp);
  440.             }
  441.             $bp[] = $this->request->request->get('bp');
  442.             $response->headers->setCookie(new Cookie("bp"json_encode(array_unique($bp)), time() + (3600 24 30)));
  443.         }
  444.     }
  445.     public function addToCartProductPack($newProductPack): void
  446.     {
  447.         $repoPC   $this->em->getRepository(ProductCart::class);
  448.         foreach ($newProductPack as $newPP)
  449.         {
  450.             /** @var ProductPack $newPP */
  451.             /** @var ProductCart $productCart */
  452.             $productCart $repoPC->findCartOnProductPack($this->cart->getHash(), $newPP->getId());
  453.             if ($newPP->isActive())
  454.             {
  455.                 if ($productCart)
  456.                 {
  457.                     $quantity $productCart->getQuantity();
  458.                     $productCart->setQuantity($newPP->getBuyMaxOne() ? : ++$quantity);
  459.                 }
  460.                 else
  461.                 {
  462.                     if ($this->checkIfPackIsCorrectCountry($newPP))
  463.                     {
  464.                         $this->setCountryToCartFromPack($newPP);
  465.                         if ($this->request->request->get('isCycle'))
  466.                         {
  467.                             /** @var ProductPackItem $firstPackItem */
  468.                             $firstPackItem $newPP->getProductPackItem()->first();
  469.                             $firstProductVariant $firstPackItem->getProductVariant();
  470.                             $productCart $repoPC->findCartOnProductVariant($this->cart->getHash(), $firstProductVariant->getId());
  471.                             if (!$productCart)
  472.                             {
  473.                                 $productCart $this->createProductCart($firstProductVariant$newPP);
  474.                             }
  475.                         }
  476.                         else
  477.                         {
  478.                             $productCart $this->createProductCart(null$newPP);
  479.                         }
  480.                     }
  481.                     else
  482.                     {
  483.                         $this->message $this->translator->trans(
  484.                             'errors.order.wrongCountry',
  485.                             [],
  486.                             'messages',
  487.                             $this->request->getSession()->get('userLocale''pl')
  488.                         );
  489.                         return;
  490.                     }
  491.                 }
  492.                 $this->em->persist($productCart);
  493.                 $this->em->flush();
  494.                 $this->em->refresh($this->cart);
  495.                 $this->facebookPixelService
  496.                     ->setEvent('AddToCart'$newPP->getId(), true)
  497.                     ->request();
  498.                 foreach ($newPP->getProductPackItem() as $item)
  499.                 {
  500.                     $pv $item->getProductVariant();
  501.                     $this->productsForGA[] = [
  502.                         'ppiId'                     => $item->getId(),
  503.                         'ppId'                      => $newPP->getId(),
  504.                         'pvId'                      => $pv->getId(),
  505.                         'productVariantNoComplete'  => $pv->getProductVariantNoComplete(),
  506.                         'tradeName'                 => $pv->getTradeName(),
  507.                         'price'                     => 0,
  508.                         'brand'                     => $pv->getMasterProduct()->getProductGroups() ? $pv->getMasterProduct()->getProductGroups()->getName() : '',
  509.                         'category'                  => $pv->getMasterProduct()->getProductType() ? $pv->getMasterProduct()->getProductType()->getName() : '',
  510.                         'quantity'                  => $productCart->getQuantity() ?? 1,
  511.                         'coupon'                    => $productCart->getCoupon() ? $productCart->getCoupon()->getCode() : null
  512.                     ];
  513.                 }
  514.                 $this->status  true;
  515.             }
  516.             else
  517.             {
  518.                 $this->message $this->translator->trans(
  519.                     'errors.order.notAvailable',
  520.                     [],
  521.                     'messages',
  522.                     $this->request->getSession()->get('userLocale''pl')
  523.                 );
  524.                 if ($productCart)
  525.                 {
  526.                     $this->cart->removeProductCart($productCart);
  527.                     $this->em->persist($productCart);
  528.                     $this->em->flush();
  529.                 }
  530.             }
  531.         }
  532.     }
  533.     private function checkIfPackIsCorrectCountry(ProductPack $pp): bool
  534.     {
  535.         /** @var ProductPackItem $productPackItem */
  536.         $productPackItem $pp->getProductPackItem()->first();
  537.         return $this->checkIfProductIsCorrectCountry($productPackItem->getProductVariant());
  538.     }
  539.     private function checkIfProductIsCorrectCountry(ProductVariant $pv null)
  540.     {
  541.         if ($this->cart->getProductCart()->count() < && $this->cart->getCountry())
  542.         {
  543.             $this->cart->setCountry(null);
  544.         }
  545.         if (empty($this->cart->getCountry()) || empty($pv))
  546.         {
  547.             return true;
  548.         }
  549.         if ($pv->getCountry())
  550.         {
  551.             if ($pv->getCountry() === $this->cart->getCountry())
  552.                 return true;
  553.             else
  554.                 return false;
  555.         }
  556.         else
  557.         {
  558.             if ($this->cart->getCountry()->getAlpha2() === 'PL')
  559.                 return true;
  560.             else
  561.                 return false;
  562.         }
  563.     }
  564.     private function setCountryToCartFromPack(ProductPack $pp): void
  565.     {
  566.         /** @var ProductPackItem $productPackItem */
  567.         $productPackItem $pp->getProductPackItem()->first();
  568.         $this->setCountryToCart($productPackItem->getProductVariant());
  569.     }
  570.     private function setCountryToCart(ProductVariant $pv null)
  571.     {
  572.         if (empty($this->cart->getCountry()))
  573.         {
  574.             if ($pv && $pv->getCountry())
  575.             {
  576.                 $this->cart->setCountry($pv->getCountry());
  577.             }
  578.             else
  579.             {
  580.                 $poland $this->em->getRepository(Country::class)->findOneByAlpha2('PL');
  581.                 $this->cart->setCountry($poland);
  582.             }
  583.         }
  584.     }
  585.     private function replaceBaseVariantsWithTargetVariants(iterable $baseProductVariants): array
  586.     {
  587.         $targetVariants = [];
  588.         /** @var ProductVariant $baseProductVariant */
  589.         foreach ($baseProductVariants as $baseProductVariant) {
  590.             $targetVariants[] = $baseProductVariant->getTargetVariant() ?? $baseProductVariant;
  591.         }
  592.         return $targetVariants;
  593.     }
  594. }