src/Controller/Website/ProductController.php line 622

Open in your IDE?
  1. <?php
  2. namespace EADPlataforma\Controller\Website;
  3. use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache;
  4. use Symfony\Component\HttpFoundation\RedirectResponse;
  5. use Symfony\Component\HttpFoundation\Request;
  6. use Symfony\Component\Routing\Annotation\Route;
  7. use EADPlataforma\Entity\Product;
  8. use EADPlataforma\Entity\ProductPage;
  9. use EADPlataforma\Entity\ProductCoupon;
  10. use EADPlataforma\Entity\ProductOffer;
  11. use EADPlataforma\Entity\ProductSuggestion;
  12. use EADPlataforma\Entity\ProductTeam;
  13. use EADPlataforma\Entity\Category;
  14. use EADPlataforma\Entity\Faq;
  15. use EADPlataforma\Entity\Course;
  16. use EADPlataforma\Entity\CycleItem;
  17. use EADPlataforma\Entity\CourseTeam;
  18. use EADPlataforma\Entity\CourseTestimonial;
  19. use EADPlataforma\Entity\Lesson;
  20. use EADPlataforma\Entity\LessonModule;
  21. use EADPlataforma\Entity\LessonXLibrary;
  22. use EADPlataforma\Entity\Exam;
  23. use EADPlataforma\Entity\Enrollment;
  24. use EADPlataforma\Entity\User;
  25. use EADPlataforma\Entity\UserSubscription;
  26. use EADPlataforma\Entity\UserCard;
  27. use EADPlataforma\Entity\UserCheckoutInfo;
  28. use EADPlataforma\Entity\Library;
  29. use EADPlataforma\Enum\CourseEnum;
  30. use EADPlataforma\Enum\CourseCertificateEnum;
  31. use EADPlataforma\Enum\EnrollmentEnum;
  32. use EADPlataforma\Enum\ProductEnum;
  33. use EADPlataforma\Enum\ProductCouponEnum;
  34. use EADPlataforma\Enum\ProductOfferEnum;
  35. use EADPlataforma\Enum\ProductPageEnum;
  36. use EADPlataforma\Enum\ProductSuggestionEnum;
  37. use EADPlataforma\Enum\CategoryEnum;
  38. use EADPlataforma\Enum\UserCardEnum;
  39. use EADPlataforma\Enum\UserCheckoutInfoEnum;
  40. use EADPlataforma\Enum\TagsMarketingEnum;
  41. use EADPlataforma\Enum\ProductOpportunityEnum;
  42. use EADPlataforma\Enum\ErrorEnum;
  43. use EADPlataforma\Util\StringUtil;
  44. /**
  45.  * @Route(
  46.  *      schemes         = {"http|https"}
  47.  * )
  48.  * @Cache(
  49.  *      maxage          = "0",
  50.  *      smaxage         = "0",
  51.  *      expires         = "now",
  52.  *      public          = false
  53.  * )
  54.  */
  55. class ProductController extends AbstractWebsiteController {
  56.     private $searchLimit 6;
  57.     private $testimonialLimit 9;
  58.     /**
  59.      * @Route(
  60.      *      path          = "/products",
  61.      *      name          = "productListSearch",
  62.      *      methods       = {"GET"},
  63.      * )
  64.      */
  65.     public function getProductSearch(Request $request) {
  66.         $poRepository $this->em->getRepository(ProductOffer::class);
  67.         $infoOffer $poRepository->getPublicStoreInfo();
  68.         if(!$infoOffer->hasProducts){
  69.             return $this->redirectToRoute('notFound');
  70.         }
  71.         $pixelService $this->generalService->getService('Marketing\\PixelService');
  72.         $pixelService->sendConversion('Search');
  73.         $search $request->get('search');
  74.         $types = [
  75.             ProductEnum::SUBSCRIPTION => (object)[ "items" => [], "total" => ], 
  76.             ProductEnum::COURSE       => (object)[ "items" => [], "total" => ],
  77.             ProductEnum::COMBO        => (object)[ "items" => [], "total" => ],
  78.             ProductEnum::LIVE         => (object)[ "items" => [], "total" => ],
  79.         ];
  80.         foreach ($types as $type => $objType) {
  81.             $objType->items $poRepository->getPublicProductOffers([
  82.                 "type" => $type
  83.                 "search" => $search
  84.                 "limit" => $this->searchLimit
  85.             ]);
  86.             $objType->total $poRepository->countPublicProductOffers(
  87.                 $type,
  88.                 null,
  89.                 $search
  90.             );
  91.             $types[$type] = $objType;
  92.         }
  93.         $this->data['search'] = $search;
  94.         $dataCourse = (object)[
  95.             "enum"  => ProductEnum::COURSE,
  96.             "name"  => $this->configuration->getLanguage('courses''product'),
  97.             "ico"   => "book",
  98.             "route" => "productListCourses",
  99.             "items" => $types[ProductEnum::COURSE]->items,
  100.             "total" => $types[ProductEnum::COURSE]->total
  101.         ];
  102.         $dataPlan = (object)[
  103.             "enum"  => ProductEnum::SUBSCRIPTION,
  104.             "name"  => $this->configuration->getLanguage('plans''product'),
  105.             "ico"   => "bookmark",
  106.             "route" => "productListPlans",
  107.             "items" => $types[ProductEnum::SUBSCRIPTION]->items,
  108.             "total" => $types[ProductEnum::SUBSCRIPTION]->total
  109.         ];
  110.         $dataCombo = (object)[
  111.             "enum"  => ProductEnum::COMBO,
  112.             "name"  => $this->configuration->getLanguage('combos''product'),
  113.             "ico"   => "package",
  114.             "route" => "productListCombos",
  115.             "items" => $types[ProductEnum::COMBO]->items,
  116.             "total" => $types[ProductEnum::COMBO]->total
  117.         ];
  118.         $dataLive = (object)[
  119.             "enum"  => ProductEnum::LIVE,
  120.             "name"  => $this->configuration->getLanguage('lives''product'),
  121.             "ico"   => "package",
  122.             "route" => "productListLives",
  123.             "items" => $types[ProductEnum::LIVE]->items,
  124.             "total" => $types[ProductEnum::LIVE]->total
  125.         ];
  126.         $this->data['hasResult'] = ProductEnum::YES;
  127.         if(
  128.             empty($types[ProductEnum::COURSE]->items) && 
  129.             empty($types[ProductEnum::SUBSCRIPTION]->items) && 
  130.             empty($types[ProductEnum::COMBO]->items) && 
  131.             empty($types[ProductEnum::LIVE]->items)
  132.         ){
  133.             $this->data['hasResult'] = ProductEnum::NO;
  134.         }
  135.         $dataSearch = [ $dataCourse$dataPlan$dataCombo$dataLive ];
  136.         $this->data['dataSearch'] = $dataSearch;
  137.         return $this->renderEAD('product/product-results.html.twig');
  138.     }
  139.     /**
  140.      * @Route(
  141.      *      path          = "/products/order/{couponKey}",
  142.      *      name          = "productListSearchOrder",
  143.      *      methods       = {"POST"},
  144.      *      defaults      = { "couponKey": null }
  145.      * )
  146.      */
  147.     public function getProductSearchOrder(Request $request) {
  148.         $this->requestUtil->setRequest($request)->setData();
  149.         $search $this->requestUtil->getField('search');
  150.         $idCategory $this->requestUtil->getField('category');
  151.         $type $this->requestUtil->getField('type');
  152.         $order $this->requestUtil->getField('order');
  153.         $order = ($order === '') ? null $order;
  154.         $offset $this->requestUtil->getField('offset');
  155.         $couponKey $request->get('couponKey');
  156.         $hasModule $this->configuration->isModuleActive("product_coupon_module");
  157.         $enrollmentService $this->generalService->getService('EnrollmentService');
  158.         $pcRepository $this->em->getRepository(ProductCoupon::class);
  159.         $poRepository $this->em->getRepository(ProductOffer::class);
  160.         $infoOffer $poRepository->getPublicStoreInfo();
  161.         if(!$infoOffer->hasProducts){
  162.             return $this->redirectToRoute('notFound');
  163.         }
  164.         $category null;
  165.         if ($idCategory !== null) {
  166.             $categoryRepository $this->em->getRepository(Category::class);
  167.             $category $categoryRepository->findOneBy([
  168.                 "deleted" => CategoryEnum::ITEM_NO_DELETED,
  169.                 "status" => CategoryEnum::PUBLISHED,
  170.                 "id" => $idCategory,
  171.             ]);
  172.         };
  173.         $results $poRepository->getPublicProductOffers([
  174.             "type" => $type,
  175.             "category" => ($category $category->getId() : null),
  176.             "search" => $search,
  177.             "limit" => $this->searchLimit,
  178.             "order" => $order,
  179.             "offset" => $offset
  180.         ]);
  181.         $productCoupon null;
  182.         if($hasModule && $category){
  183.             $productCoupon $pcRepository->findValidProductCouponByCategory(
  184.                 $couponKey
  185.                 $category
  186.             );
  187.         }
  188.         $this->data['productCoupon'] = $productCoupon;
  189.         if($productCoupon){
  190.             foreach ($results as $key => $productOffer) {
  191.                 $amount $productOffer->getPriceReal();
  192.                 $amount $pcRepository->applyDiscount($productCoupon$amount);
  193.                 if($amount 0){
  194.                     $productOffer->setPriceRealCopy($amount);
  195.                 }else{
  196.                     if($this->user){
  197.                         $productCoupon->setUsageNumber(
  198.                             $productCoupon->getUsageNumber() + 1
  199.                         );
  200.                         $this->em->flush();
  201.                         $enrollmentService->setOrigin(EnrollmentEnum::ORIGIN_COUPOM);
  202.                         $enrollmentService->setCouponKey($couponKey);
  203.                         $enrollmentService->enrollUserByProduct(
  204.                             $this->user,
  205.                             $productOffer->getProduct()
  206.                         );
  207.                     }else{
  208.                         $hash base64_encode($request->getUri());
  209.                         $url $this->generalService->generateUrl('login', [ 
  210.                             "hash" => $hash 
  211.                         ]);
  212.                         $redirectResponse = new RedirectResponse($url);
  213.                         $redirectResponse->headers->set('Content-Type''text/html');
  214.                         $redirectResponse->send();
  215.                         exit;
  216.                     }
  217.                 }
  218.             }
  219.         }
  220.         $this->data['items'] = $results;
  221.         return $this->renderEAD('product/product-results-items.html.twig');
  222.     }
  223.     /**
  224.      * @Route(
  225.      *      path          = "/product/suggestion",
  226.      *      name          = "productListSuggestionSearch",
  227.      *      methods       = {"GET"},
  228.      * )
  229.      */
  230.     public function getProductSuggestionSearch(Request $request) {
  231.         $search $request->get('search');
  232.         
  233.         $poRepository $this->em->getRepository(ProductOffer::class);
  234.         $infoOffer $poRepository->getPublicStoreInfo();
  235.         if(!$infoOffer->hasProducts){
  236.             return $this->eadResponse(nullErrorEnum::ACTION_INVALID);
  237.         }
  238.         $data $poRepository->getPublicProductOffersSimply(
  239.             null,
  240.             null,
  241.             $search,
  242.             5
  243.         );
  244.         $typeRoute = [
  245.             ProductEnum::COURSE => 'productDetailCourse',
  246.             ProductEnum::COMBO => 'productDetailCombo',
  247.             ProductEnum::SUBSCRIPTION => 'productDetailPlan',
  248.         ];
  249.         $productTypeTextArr = [
  250.             ProductEnum::COURSE => 'curso',
  251.             ProductEnum::COMBO => 'combo',
  252.             ProductEnum::SUBSCRIPTION => 'plano',
  253.         ];
  254.         $aux = [
  255.             'firstLink' => null,
  256.             'items' => [],
  257.         ];
  258.         foreach ($data as $key => $value) {
  259.             $value = (object)$value;
  260.             
  261.             if(
  262.                 !empty($typeRoute[$value->type]) && 
  263.                 !empty($productTypeTextArr[$value->type])
  264.             ){
  265.                 $value->offerLink $value->externalPage;
  266.                 if(empty($value->externalPage)){
  267.                     $params = [
  268.                         "type" => $productTypeTextArr[$value->type],
  269.                         "slug" => $value->productLink
  270.                     ];
  271.                     $value->offerLink $this->generateUrl(
  272.                         $typeRoute[$value->type],
  273.                         $params
  274.                     );
  275.                 }
  276.                 
  277.                 $aux['items'][$key] = $value;
  278.             }
  279.         }
  280.         $aux['firstLink'] = "{$this->generateUrl('productListSearch')}?search={$search}";
  281.         return $this->eadResponse($aux);
  282.     }
  283.     /**
  284.      * @Route(
  285.      *      path          = "/{type}",
  286.      *      name          = "productListCourses",
  287.      *      methods       = {"GET"},
  288.      *      requirements  = {"type"="cursos|courses"}
  289.      * )
  290.      */
  291.     public function getProductCourse(Request $request) {
  292.         
  293.         $poRepository $this->em->getRepository(ProductOffer::class);
  294.         $infoOffer $poRepository->getPublicStoreInfo();
  295.         if(!$infoOffer->hasProducts){
  296.             return $this->redirectToRoute('notFound');
  297.         }
  298.         $productOffers $poRepository->getPublicProductOffers([
  299.             "type" => ProductEnum::COURSE
  300.         ]);
  301.         if(empty($productOffers)){
  302.             return $this->redirectToRoute('notFound');
  303.         }
  304.         $this->data['productOffers'] = $productOffers;
  305.         $this->data['title'] = $this->configuration->getLanguage('courses''product');
  306.         return $this->renderEAD('product/product-list.html.twig');
  307.     }
  308.     /**
  309.      * @Route(
  310.      *      path          = "/combos",
  311.      *      name          = "productListCombos",
  312.      *      methods       = {"GET"},
  313.      * )
  314.      */
  315.     public function getProductCombo(Request $request) {
  316.         $poRepository $this->em->getRepository(ProductOffer::class);
  317.         $infoOffer $poRepository->getPublicStoreInfo();
  318.         if(!$infoOffer->hasProducts){
  319.             return $this->redirectToRoute('notFound');
  320.         }
  321.         $productOffers $poRepository->getPublicProductOffers([
  322.             "type" => ProductEnum::COMBO
  323.         ]);
  324.         if(empty($productOffers)){
  325.             return $this->redirectToRoute('notFound');
  326.         }
  327.         $this->data['productOffers'] = $productOffers;
  328.         $this->data['title'] = "Combos";
  329.         return $this->renderEAD('product/product-list.html.twig');
  330.     }
  331.     /**
  332.      * @Route(
  333.      *      path          = "/{type}",
  334.      *      name          = "productListPlans",
  335.      *      methods       = {"GET"},
  336.      *      requirements  = {"type"="planos|plans"}
  337.      * )
  338.      */
  339.     public function getProductPlan(Request $request) {
  340.         
  341.         if(!$this->configuration->isModuleActive('product_subscription_module')){
  342.             return $this->redirectToRoute('notFound');
  343.         }
  344.         $poRepository $this->em->getRepository(ProductOffer::class);
  345.         $infoOffer $poRepository->getPublicStoreInfo();
  346.         if(!$infoOffer->hasProducts){
  347.             return $this->redirectToRoute('notFound');
  348.         }
  349.         $planProductOffers $poRepository->getPublicProductOffers([
  350.             "type" => ProductEnum::SUBSCRIPTION
  351.         ]);
  352.         if(empty($planProductOffers)){
  353.             return $this->redirectToRoute('notFound');
  354.         }
  355.         $lMRepository $this->em->getRepository(LessonModule::class);
  356.         $lessonRepository $this->em->getRepository(Lesson::class);
  357.         $examRepository $this->em->getRepository(Exam::class);
  358.         foreach ($planProductOffers as $key => $planProductOffer) {
  359.             $planProduct $planProductOffer->getProduct();
  360.             $lmNumber $lMRepository->getLessonModuleNumberByProduct($planProduct);
  361.             $planProduct->lessonModuleNumber $lmNumber;
  362.             $planProduct->lessonNumber $lessonRepository->getLessonNumberByProduct(
  363.                 $planProduct
  364.             );
  365.             $planProduct->examNumber $examRepository->getExamNumberByProduct(
  366.                 $planProduct
  367.             );
  368.             $planProductOffer->setProduct($planProduct);
  369.             $planProductOffers[$key] = $planProductOffer;
  370.         }
  371.         $this->data['planProductOffers'] = $planProductOffers;
  372.         return $this->renderEAD('product/product-plan-list.html.twig');
  373.     }
  374.     /**
  375.      * @Route(
  376.      *      path          = "/{type}/{slug}/{couponKey}",
  377.      *      name          = "productListCategory",
  378.      *      methods       = {"GET"},
  379.      *      defaults      = { "couponKey": null },
  380.      *      requirements  = {"type"="cursos|courses|planos|plans|combos|produtos|products"}
  381.      * )
  382.      */
  383.     public function getByProductCategory(Request $request) {
  384.         $limit 6;
  385.         $hasModule $this->configuration->isModuleActive("product_coupon_module");
  386.         $enrollmentService $this->generalService->getService('EnrollmentService');
  387.         $poRepository $this->em->getRepository(ProductOffer::class);
  388.         $categoryRepository $this->em->getRepository(Category::class);
  389.         $pcRepository $this->em->getRepository(ProductCoupon::class);
  390.         $infoOffer $poRepository->getPublicStoreInfo();
  391.         if(!$infoOffer->hasProducts){
  392.             return $this->redirectToRoute('notFound');
  393.         }
  394.         $couponKey $request->get('couponKey');
  395.         $category $categoryRepository->findOneBy([
  396.             "deleted" => CategoryEnum::ITEM_NO_DELETED,
  397.             "status" => CategoryEnum::PUBLISHED,
  398.             "slug" => $request->get('slug'),
  399.         ]);
  400.         if(!$category){
  401.             return $this->redirectToRoute('notFound');
  402.         }
  403.         $productCoupon null;
  404.         if($hasModule){
  405.             $productCoupon $pcRepository->findValidProductCouponByCategory(
  406.                 $couponKey
  407.                 $category
  408.             );
  409.         }
  410.         $this->data['productCoupon'] = $productCoupon;
  411.         $types = [
  412.             ProductEnum::SUBSCRIPTION => (object)[ "items" => [], "total" => ], 
  413.             ProductEnum::COURSE       => (object)[ "items" => [], "total" => ],
  414.             ProductEnum::COMBO        => (object)[ "items" => [], "total" => ],
  415.             ProductEnum::LIVE         => (object)[ "items" => [], "total" => ],
  416.         ];
  417.         foreach ($types as $type => $objType) {
  418.             $objType->items $poRepository->getPublicProductOffers([
  419.                 "type" => $type
  420.                 "category" => ($category $category->getId() : null), 
  421.                 "limit" => $this->searchLimit
  422.             ]);
  423.             if($productCoupon){
  424.                 foreach ($objType->items as $key => $productOffer) {
  425.                     $amount $productOffer->getPriceReal();
  426.                     $amount $pcRepository->applyDiscount($productCoupon$amount);
  427.                     if($amount 0){
  428.                         $productOffer->setPriceRealCopy($amount);
  429.                     }else{
  430.                         if($this->user){
  431.                             $productCoupon->setUsageNumber(
  432.                                 $productCoupon->getUsageNumber() + 1
  433.                             );
  434.                             $this->em->flush();
  435.                             $enrollmentService->setOrigin(EnrollmentEnum::ORIGIN_COUPOM);
  436.                             $enrollmentService->setCouponKey($couponKey);
  437.                             $enrollmentService->enrollUserByProduct(
  438.                                 $this->user,
  439.                                 $productOffer->getProduct()
  440.                             );
  441.                         }else{
  442.                             $hash base64_encode($request->getUri());
  443.                             $url $this->generalService->generateUrl('login', [ "hash" => $hash ]);
  444.                             $redirectResponse = new RedirectResponse($url);
  445.                             $redirectResponse->headers->set('Content-Type''text/html');
  446.                             $redirectResponse->send();
  447.                             exit;
  448.                         }
  449.                     }
  450.                 }
  451.             }
  452.             $objType->total $poRepository->countPublicProductOffers(
  453.                 $type,
  454.                 $category
  455.             );
  456.             $types[$type] = $objType;
  457.         }
  458.         $this->data['category'] = $category;
  459.         $dataCourse = (object)[
  460.             "enum"  => ProductEnum::COURSE,
  461.             "name"  => "Cursos",
  462.             "ico"   => "book",
  463.             "route" => "productListCourses",
  464.             "items" => $types[ProductEnum::COURSE]->items,
  465.             "total" => $types[ProductEnum::COURSE]->total
  466.         ];
  467.         $dataPlan = (object)[
  468.             "enum"  => ProductEnum::SUBSCRIPTION,
  469.             "name"  => "Planos",
  470.             "ico"   => "bookmark",
  471.             "route" => "productListPlans",
  472.             "items" => $types[ProductEnum::SUBSCRIPTION]->items,
  473.             "total" => $types[ProductEnum::SUBSCRIPTION]->total
  474.         ];
  475.         $dataCombo = (object)[
  476.             "enum"  => ProductEnum::COMBO,
  477.             "name"  => "Combos",
  478.             "ico"   => "package",
  479.             "route" => "productListCombos",
  480.             "items" => $types[ProductEnum::COMBO]->items,
  481.             "total" => $types[ProductEnum::COMBO]->total
  482.         ];
  483.         $dataLive = (object)[
  484.             "enum"  => ProductEnum::LIVE,
  485.             "name"  => "Lives",
  486.             "ico"   => "package",
  487.             "route" => "productListLives",
  488.             "items" => $types[ProductEnum::LIVE]->items,
  489.             "total" => $types[ProductEnum::LIVE]->total
  490.         ];
  491.         $this->data['hasResult'] = ProductEnum::YES;
  492.         if(
  493.             empty($types[ProductEnum::COURSE]->items) && 
  494.             empty($types[ProductEnum::SUBSCRIPTION]->items) && 
  495.             empty($types[ProductEnum::COMBO]->items) && 
  496.             empty($types[ProductEnum::LIVE]->items)
  497.         ){
  498.             $this->data['hasResult'] = ProductEnum::NO;
  499.         }
  500.         $dataSearch = [ $dataCourse$dataPlan$dataCombo$dataLive ];
  501.         $this->data['dataSearch'] = $dataSearch;
  502.         $this->data['search'] = '';
  503.         return $this->renderEAD('product/product-results.html.twig');
  504.     }
  505.     /**
  506.      * @Route(
  507.      *      path          = "/{type}/{slug}/{offerHash}",
  508.      *      name          = "productDetailCourse",
  509.      *      methods       = {"GET"},
  510.      *      defaults      = { "offerHash": null },
  511.      *      requirements  = {"type"="curso|course"}
  512.      * )
  513.      */
  514.     public function getProductCourseDetailPage(Request $request) {
  515.         $this->requestUtil->setRequest($request)->setData();
  516.         $utmsUrl http_build_query($this->requestUtil->getData());   
  517.         $this->data['utmsUrl'] = $utmsUrl;
  518.         $slug $request->get('slug');
  519.         $type $request->get('type');
  520.         $offerHash $request->get('offerHash');
  521.         $couponKey $request->get('coupon');
  522.         $pageId $request->get('page');
  523.         
  524.         $productType ProductEnum::COURSE;
  525.         $poRepository $this->em->getRepository(ProductOffer::class);
  526.         $productOffer $poRepository->getProductBySlug(
  527.             $slug,
  528.             $productType,
  529.             $offerHash
  530.         );
  531.         if(!$productOffer){
  532.             $productOffer $poRepository->getProductBySlug(
  533.                 $slug,
  534.                 $productType
  535.             );
  536.             $couponKey $offerHash;
  537.             if(!$productOffer){
  538.                 return $this->redirectToRoute('notFound');
  539.             }
  540.         }
  541.         $product $productOffer->getProduct();
  542.         if($product->getType() != $productType){
  543.             return $this->redirectToRoute('notFound');
  544.         }
  545.         $productOffer $poRepository->returnProductOfferOrProductNextClean($productOffer);
  546.         $productPage $productOffer->getProductPage();
  547.         if(!empty($pageId)){
  548.             $productPage $this->em->getRepository(ProductPage::class)->find($pageId);
  549.         }
  550.         if(!$productPage){
  551.             return $this->redirectToRoute('notFound');
  552.         }
  553.         $externalPage $productPage->getExternalPage();
  554.         $externalPageLink $productPage->getExternalPageLink();
  555.         if($externalPage == ProductEnum::YES && !empty($externalPageLink)){
  556.             return $this->redirect($externalPageLink301);
  557.         }
  558.         $this->data['productPage'] = $productPage;
  559.         $productRelateds $product->getProductRelated();
  560.         $courseRepository $this->em->getRepository(Course::class);
  561.         $courses $courseRepository->getCoursesByProduct($product->getId());
  562.         $this->data['formName'] = "formFastUserRegister";
  563.         $this->data['accessPeriod'] = null;
  564.         $this->data['support'] = CourseEnum::NO;
  565.         $this->data['supportPeriod'] = null;
  566.         $this->data['lifetimePeriod'] = CourseEnum::NO;
  567.         $this->data['certificate'] = CourseEnum::NO;
  568.         $this->data['generateCertificate'] = CourseCertificateEnum::NO;
  569.         $this->data['lessonModules'] = [];
  570.         $this->data['couponKey'] = $couponKey;
  571.         $this->data['couponKeyValid'] = false;
  572.         $this->data['productCoupon'] = null;
  573.         $hasModule $this->configuration->isModuleActive("product_coupon_module");
  574.         $enrollmentService $this->generalService->getService('EnrollmentService');
  575.         $productRepository $this->em->getRepository(Product::class);
  576.         $productRepository->saveProductInCache($product);
  577.         $pcRepository $this->em->getRepository(ProductCoupon::class);
  578.         $this->data['productOfferCouponTotal'] = $pcRepository->countPublicCouponByProductOffer(
  579.             $productOffer
  580.         );
  581.         if(!empty($couponKey) && $hasModule){
  582.             $productCoupon $pcRepository->findValidProductCouponByProductOffer(
  583.                 $couponKey,
  584.                 $productOffer
  585.             );
  586.             if($productCoupon){
  587.                 $amount $productOffer->getPriceReal();
  588.                 $amount $pcRepository->applyDiscount($productCoupon$amount);
  589.                 if($amount 0){
  590.                     $this->data['productCoupon'] = $productCoupon;
  591.                     $this->data['couponKeyValid'] = true;
  592.                     $productOffer->setPriceRealCopy($amount);
  593.  
  594.                 }else{
  595.                     if($this->user){
  596.                         $productCoupon->setUsageNumber(
  597.                             $productCoupon->getUsageNumber() + 1
  598.                         );
  599.                         $this->em->flush();
  600.                         $enrollmentService->setOrigin(EnrollmentEnum::ORIGIN_COUPOM);
  601.                         $enrollmentService->setCouponKey($couponKey);
  602.                         $enrollmentService->enrollUserByProduct(
  603.                             $this->user,
  604.                             $productOffer->getProduct()
  605.                         );
  606.                     }else{
  607.                         
  608.                         $params = [
  609.                             "poID" => $productOffer->getId(),
  610.                             "pcID" => $productCoupon->getId(),
  611.                         ];
  612.                         return $this->redirectToRoute('cartAdd'$params);
  613.                     }
  614.                 }
  615.             }
  616.         }
  617.        
  618.         $psRepository $this->em->getRepository(ProductSuggestion::class);
  619.         $productOfferSuggestions $psRepository->getProductSuggestionsByOfferOrigin(
  620.             $productOffer,
  621.             ProductSuggestionEnum::EXECUTE_IN_PRODUCT_PAGE
  622.         );
  623.         $productOfferSuggestionsAddCart $psRepository->getProductSuggestionsByOfferOrigin(
  624.             $productOffer,
  625.             ProductSuggestionEnum::EXECUTE_ON_ADD_CART
  626.         );
  627.         $this->data['emptyProductSuggestion'] = true;
  628.         if(!empty($productOfferSuggestions) || !empty($productOfferSuggestionsAddCart)){
  629.             $this->data['emptyProductSuggestion'] = false;
  630.         }
  631.         if($this->data['productCoupon'] && $hasModule){
  632.             foreach ($productOfferSuggestions as $key => $offerSuggestion) {
  633.                 $pcSuggestion $pcRepository->findValidProductCouponByIdAndProductOffer(
  634.                     $this->data['productCoupon']->getId(), 
  635.                     $offerSuggestion,
  636.                     true
  637.                 );
  638.                 if($pcSuggestion){
  639.                     $amount $offerSuggestion->getPriceReal();
  640.                     $amount $pcRepository->applyDiscount($pcSuggestion$amount);
  641.                     if($amount 0){
  642.                         $offerSuggestion->setPriceRealCopy($amount);
  643.                     }else{
  644.                         if($this->user){
  645.                             $pcSuggestion->setUsageNumber(
  646.                                 $pcSuggestion->getUsageNumber() + 1
  647.                             );
  648.                             $this->em->flush();
  649.                             $enrollmentService->setOrigin(EnrollmentEnum::ORIGIN_COUPOM);
  650.                             $enrollmentService->setCouponKey($couponKey);
  651.                             $enrollmentService->enrollUserByProduct(
  652.                                 $this->user,
  653.                                 $offerSuggestion->getProduct()
  654.                             );
  655.                         }else{
  656.                             $hash base64_encode($request->getUri());
  657.                             $url $this->generalService->generateUrl('login', [ 
  658.                                 "hash" => $hash 
  659.                             ]);
  660.                             $redirectResponse = new RedirectResponse($url);
  661.                             $redirectResponse->headers->set('Content-Type''text/html');
  662.                             $redirectResponse->send();
  663.                             exit;
  664.                         }
  665.                     }
  666.                 }
  667.                 $productOfferSuggestions[$key] = $offerSuggestion;
  668.             }
  669.         }
  670.         $this->data['productOfferSuggestions'] = $productOfferSuggestions;
  671.         $numberUtil $this->generalService->getUtil('NumberUtil');
  672.         $parcelInfo $numberUtil->getNumberMaxParcel(
  673.             $productOffer->getPriceRealCopy(true),
  674.             $poRepository->getInstallmentNumberMax($productOffer),
  675.             $poRepository->getFreeInstallment($productOffer),
  676.             $productOffer->getSaleOption(),
  677.             $productOffer->getTypeCheckout(),
  678.             false
  679.         );
  680.         $this->data['parcelInfo'] = $parcelInfo;
  681.         $this->data['useCard'] = $poRepository->produtOfferAllowCard($productOffer);
  682.         $this->data['useBill'] = $poRepository->produtOfferAllowBill($productOffer);
  683.         $this->data['usePix'] = $poRepository->produtOfferAllowPix($productOffer);
  684.         //ProductOffer Related
  685.         $productOffersRelateds $poRepository->getProductRelatedOffers(
  686.             $product
  687.         );
  688.         //Permission to view draft page
  689.         if(
  690.             $productOffer->getStatus() == ProductOfferEnum::DRAFT || 
  691.             $product->getStatus() == ProductEnum::DRAFT
  692.         ){
  693.             $this->checkUserSession($request);
  694.             $permission $this->userPermissionUtil->getPermission("product""see");
  695.             if($this->userPermissionUtil->isLow($permission)){
  696.                 return $this->redirectToRoute('notFound');
  697.             }
  698.             $isInTeam $this->em->getRepository(ProductTeam::class)->userExistInProductTeam(
  699.                 $product,
  700.                 $this->user
  701.             );
  702.             if(!$isInTeam && $this->userPermissionUtil->isMiddle($permission)){
  703.                 return $this->redirectToRoute('notFound');
  704.             }
  705.         }
  706.         $this->data['productOffer'] = $productOffer;
  707.         $this->data['product'] = $product;
  708.         //FAQ
  709.         $this->data['faqs'] = $this->em->getRepository(Faq::class)->getFaqForProductDetail(
  710.             $product
  711.         );
  712.         //Course Team
  713.         $teachers $this->em->getRepository(User::class)->getUserTeachersFromProduct(
  714.             $product
  715.         );
  716.         $this->data['courseTotal'] = 0;
  717.         $this->data['courses'] = $courses;
  718.         $this->data['teacherSection'] = (object)[
  719.             "teachers" => $teachers,
  720.             "isCenterTitle" => false,
  721.             "title" => $this->configuration->getLanguage('instructors''product'),
  722.             "showSubtitle" => false,
  723.             "subtitle" => '',
  724.             "showBtnToAll" => false,
  725.         ];
  726.         $this->data['productOffersRelatedsSection'] = (object)[
  727.             "title" => $this->configuration->getLanguage('related_products''product'),
  728.             "subtitle" => $this->configuration->getLanguage('extend_your_knowledge''product'),
  729.             "name" => "product-related",
  730.             "items" => $productOffersRelateds,
  731.             "background" => false,
  732.             "expand" => false,
  733.             "slider" => true,
  734.         ];
  735.         $this->data['planCoursesSection'] = (object)[
  736.             "title" => $this->configuration->getLanguage('courses_included_plan''product'),
  737.             "subtitle" => "",
  738.             "name" => "product-plan-course",
  739.             "items" => $courses,
  740.             "background" => true,
  741.             "expand" => false,
  742.             "slider" => false,
  743.             "isCourse" => true,
  744.             "itemsTotal" => $this->data['courseTotal']
  745.         ];
  746.         $courseTestimonialRepository $this->em->getRepository(CourseTestimonial::class);
  747.         //Course Stars
  748.         $this->data['scoreProduct'] = $courseTestimonialRepository->getScoreByProduct(
  749.             $product
  750.         );
  751.         $this->data['scoreProduct']->splitScore = [
  752.             $this->data['scoreProduct']->fiveStar,
  753.             $this->data['scoreProduct']->fourStar,
  754.             $this->data['scoreProduct']->threeStar,
  755.             $this->data['scoreProduct']->twoStar,
  756.             $this->data['scoreProduct']->oneStar,
  757.         ];
  758.         //Course Testimonials
  759.         $this->data['courseTestimonials'] = $courseTestimonialRepository->getTestimonialApprovedRandom(
  760.             $this->testimonialLimit,
  761.             $product
  762.         );
  763.         foreach ($this->data['courseTestimonials'] as $key => $value) {
  764.             
  765.             $value['testimonial'] = StringUtil::encodeStringStatic($value['testimonial']);
  766.             $value['userName'] = StringUtil::encodeStringStatic($value['userName']);
  767.             $this->data['courseTestimonials'][$key] = $value;
  768.         }
  769.         
  770.         //Lesson Module Total
  771.         $lessonModuleRepository $this->em->getRepository(LessonModule::class);
  772.         $this->data['lessonModuleTotal'] = $lessonModuleRepository->getLessonModuleNumberByProduct(
  773.             $product
  774.         );
  775.         //Lesson Total
  776.         $lessonRepository $this->em->getRepository(Lesson::class);
  777.         $this->data['lessonTotal'] = $lessonRepository->getLessonNumberByProduct(
  778.             $product
  779.         );
  780.         $productOffersSubscriptionAll = [];
  781.         $dateLastUpdate null;
  782.         $auxCourses = [];
  783.         foreach ($courses as $key => $course) {
  784.             if($course->getStatus() == CourseEnum::PUBLISHED){
  785.                 $lastUpdate $course->getDateUpdate();
  786.                 if(empty($dateLastUpdate) || $lastUpdate $dateLastUpdate){
  787.                     $dateLastUpdate $lastUpdate;
  788.                 }
  789.                 if($course->getCertificate() == CourseEnum::YES){
  790.                     $this->data['certificate'] = CourseEnum::YES;
  791.                 }
  792.                 $productOffersSubscription $poRepository->getProductOffersByCourse(
  793.                     $course,
  794.                     ProductEnum::SUBSCRIPTION
  795.                 );
  796.                 $productOffersSubscriptionAll array_merge(
  797.                     $productOffersSubscriptionAll,
  798.                     $productOffersSubscription
  799.                 );
  800.                 $auxCourses[] = $course;
  801.             }
  802.         }
  803.         $this->data['dateLastUpdate'] = $dateLastUpdate;
  804.         $this->data['productOffersSubscriptionSection'] = (object)[
  805.             "title" => $this->configuration->getLanguage('you_can_expand''product'),
  806.             "subtitle" => $this->configuration->getLanguage('sign_up_for_a_plan''product'),
  807.             "name" => "product-subscription-course",
  808.             "items" => $productOffersSubscriptionAll,
  809.             "background" => true,
  810.             "expand" => false,
  811.             "slider" => false,
  812.             "isCourse" => true,
  813.             "itemsTotal" => $this->data['courseTotal']
  814.         ];
  815.         //Sale number limit
  816.         $poRepository $this->em->getRepository(ProductOffer::class);
  817.         $this->data['saleLimitRemaining'] = $poRepository->getProductOfferSaleLimitRemaining(
  818.             $productOffer
  819.         );
  820.         
  821.         //Courses
  822.         $this->data['courses'] = $auxCourses;
  823.         //Product time total
  824.         $this->data['timeTotal'] = $courseRepository->getAllCourseTimeByProduct(
  825.             $product->getId()
  826.         );
  827.         //Product files total
  828.         $lessonXLibraryRepository $this->em->getRepository(LessonXLibrary::class);
  829.         $this->data['fileTotal'] = $lessonXLibraryRepository->getLessonXLibraryFilesByProduct(
  830.             $product
  831.         );
  832.         $this->data['userSubscriptionTotal'] = 0;
  833.         $this->data['enrollmentTotal'] = 0;
  834.         $this->data['keyCaptcha'] = $this->createCaptchaKey($request);
  835.         if(!empty(count($courses))){
  836.             $course $courses[0];
  837.             $enrollmentRepository $this->em->getRepository(Enrollment::class);
  838.             $this->data['enrollmentTotal'] = $enrollmentRepository->countEnrollmentsByCourse(
  839.                 $course->getId(),
  840.                 EnrollmentEnum::STATUS_ACTIVE
  841.             );
  842.             $cycleItemRepository $this->em->getRepository(CycleItem::class);
  843.             $this->data['accessPeriod'] = $course->getSupport();
  844.             $accessPeriod $cycleItemRepository->getPeriodByDay(
  845.                 $course->getAccessPeriod()
  846.             );
  847.             $suportPeriod $cycleItemRepository->getPeriodByDay(
  848.                 $course->getSupportPeriod()
  849.             );
  850.         
  851.             if($accessPeriod){
  852.                 $this->data['accessPeriod'] = $accessPeriod->getName();
  853.             }
  854.             if($suportPeriod){
  855.                 $this->data['supportPeriod'] = $suportPeriod->getName();
  856.             }
  857.             $this->data['lifetimePeriod'] = $course->getLifetimePeriod();
  858.             //Lesson modules and lessons
  859.             $lessonModules $lessonModuleRepository->getLessonModulesByCourse($course);
  860.             $lessonRepository $this->em->getRepository(Lesson::class);
  861.             
  862.             foreach ($lessonModules as $key => $lessonModule) {
  863.                 $lessonModule->lessons $lessonRepository->getLessonByLessonModule(
  864.                     $lessonModule
  865.                 );
  866.                 $lessonModule->workloads $lessonModuleRepository->getLessonModuleTime(
  867.                     $lessonModule
  868.                 );
  869.             }
  870.             $this->data['lessonModules'] = $lessonModules;
  871.         }
  872.         if($this->user){
  873.             $marketingService $this->generalService->getService(
  874.                 'Marketing\\MarketingService'
  875.             );
  876.             $marketingService->setTag(TagsMarketingEnum::TAG_VISITED_COURSE_PAGE);
  877.             $marketingService->setTextComplement($product->getTitle());
  878.             $marketingService->setUser($this->user);
  879.             $marketingService->setProductOffer($productOffer);
  880.             $marketingService->setOpportunity(ProductOpportunityEnum::TAG_VISITED_COURSE_PAGE);
  881.             $marketingService->send();
  882.         }
  883.         $pagarMeTransaction $this->generalService->getService(
  884.             'PagarMe\\PagarMeTransaction'
  885.         );
  886.         $paymentConfig $this->configuration->getPaymentConfig();
  887.         $installmentsOptions $pagarMeTransaction->calculateInstallments([
  888.             'amount' => $productOffer->getPriceRealCopy(true),
  889.             'free_installments' => $poRepository->getFreeInstallment($productOffer),
  890.             'max_installments' => $parcelInfo->maxInstallments,
  891.             'interest_rate' => $paymentConfig->installmentInterest
  892.         ]);
  893.         $this->data['installmentsOptions'] = (array)$installmentsOptions;
  894.         $userCards null;
  895.         $userCheckoutInfos null;
  896.         if($this->user){
  897.             $userCardRepository $this->em->getRepository(UserCard::class);
  898.             $userCards $userCardRepository->findBy([
  899.                 "user" => $this->user->getId(),
  900.                 "deleted" => UserCardEnum::ITEM_NO_DELETED
  901.             ]);
  902.             $userCheckoutInfoRepository $this->em->getRepository(UserCheckoutInfo::class);
  903.             $userCheckoutInfos $userCheckoutInfoRepository->findBy([
  904.                 "user" => $this->user->getId(),
  905.                 "deleted" => UserCheckoutInfoEnum::ITEM_NO_DELETED
  906.             ], [ "default" => "DESC" ]);
  907.         }
  908.         $this->data["isOnSale"] = $poRepository->checkProductOfferIsOnSale($productOffer);
  909.         $this->data["userCards"] = $userCards;
  910.         $this->data["userCheckoutInfos"] = $userCheckoutInfos;
  911.         $this->data["productOffers"] = [ $productOffer ];
  912.         $credentials null;
  913.         $videoLibrary $productPage->getLibrary();
  914.         if($videoLibrary){
  915.             $libraryRepository $this->em->getRepository(Library::class);
  916.             $credentials $libraryRepository->getVideoCredentials($videoLibrary);
  917.         }
  918.         $this->data["credentials"] = $credentials;
  919.         if($productPage->getType() == ProductPageEnum::TYPE_LAND_PAGE){
  920.             $pixelService $this->generalService->getService('Marketing\\PixelService');
  921.             $pixelService->sendConversion('AddToCart', (object)[
  922.                 "content_ids" => [ $productOffer->getId() ],
  923.                 "content_name" => $productOffer->getTitle(),
  924.                 "currency" => $productOffer->getCurrencyCode(),
  925.                 "value" => $productOffer->getPriceReal(),
  926.             ]);
  927.             if($this->user && $productOffer->getSaleOption() == ProductOfferEnum::FREE){
  928.                 $enrollmentService $this->generalService->getService(
  929.                     'EnrollmentService'
  930.                 );
  931.                 $enrollmentService->setOrigin(EnrollmentEnum::ORIGIN_FREE);
  932.                 $enrollmentService->enrollUserByProduct(
  933.                     $this->user,
  934.                     $productOffer->getProduct()
  935.                 );
  936.             }
  937.             return $this->renderEAD('product/landingpage/index.html.twig');
  938.         }
  939.         return $this->renderEAD("product/product-detail.html.twig");
  940.     }
  941.     /**
  942.      * @Route(
  943.      *      path          = "/{type}/{slug}/{offerHash}",
  944.      *      name          = "productDetailPlan",
  945.      *      methods       = {"GET"},
  946.      *      defaults      = { "offerHash": null },
  947.      *      requirements  = {"type"="plano|plan"}
  948.      * )
  949.      */
  950.     public function getProductPlanDetailPage(Request $request) {
  951.         $this->requestUtil->setRequest($request)->setData();
  952.         $utmsUrl http_build_query($this->requestUtil->getData());   
  953.         $this->data['utmsUrl'] = $utmsUrl;
  954.         $slug $request->get('slug');
  955.         $type $request->get('type');
  956.         $offerHash $request->get('offerHash');
  957.         $couponKey $request->get('coupon');
  958.         $pageId $request->get('page');
  959.         $productType ProductEnum::SUBSCRIPTION;
  960.         $productRepository $this->em->getRepository(Product::class);
  961.         $poRepository $this->em->getRepository(ProductOffer::class);
  962.         $poRepository $this->em->getRepository(ProductOffer::class);
  963.         $productOffer $poRepository->getProductBySlug(
  964.             $slug,
  965.             $productType,
  966.             $offerHash
  967.         );
  968.         if(!$productOffer){
  969.             $productOffer $poRepository->getProductBySlug(
  970.                 $slug,
  971.                 $productType
  972.             );
  973.             if(!$productOffer){
  974.                 return $this->redirectToRoute('notFound');
  975.             }
  976.             
  977.             $couponKey $offerHash;
  978.         }
  979.         if(
  980.             (
  981.                 $productOffer->getDefault() == ProductEnum::NO ||
  982.                 $productOffer->getSpotlight() == ProductEnum::NO
  983.             ) && empty($offerHash)
  984.         ){
  985.             $offerHash $productOffer->getOfferLink();
  986.         }
  987.         $product $productOffer->getProduct();
  988.         if($product->getType() != $productType){
  989.             return $this->redirectToRoute('notFound');
  990.         }
  991.         $productRelateds $product->getProductRelated();
  992.         $courseRepository $this->em->getRepository(Course::class);
  993.         $courses $courseRepository->getCoursesByProduct($product->getId());
  994.         $monthOffer $poRepository->getDefaultOrCustomByCycle(
  995.             $product,
  996.             ProductOfferEnum::CYCLE_MONTHLY,
  997.             $offerHash
  998.         );
  999.         $quarterlyOffer $poRepository->getDefaultOrCustomByCycle(
  1000.             $product,
  1001.             ProductOfferEnum::CYCLE_QUARTERLY,
  1002.             $offerHash
  1003.         );
  1004.         $semiannualOffer $poRepository->getDefaultOrCustomByCycle(
  1005.             $product,
  1006.             ProductOfferEnum::CYCLE_SEMIANNUAL,
  1007.             $offerHash
  1008.         );
  1009.         $yearlyOffer $poRepository->getDefaultOrCustomByCycle(
  1010.             $product,
  1011.             ProductOfferEnum::CYCLE_YEARLY,
  1012.             $offerHash
  1013.         );
  1014.         $biennialOffer $poRepository->getDefaultOrCustomByCycle(
  1015.             $product,
  1016.             ProductOfferEnum::CYCLE_BIENNIAL,
  1017.             $offerHash
  1018.         );
  1019.         $triennialOffer $poRepository->getDefaultOrCustomByCycle(
  1020.             $product,
  1021.             ProductOfferEnum::CYCLE_TRIENNIAL,
  1022.             $offerHash
  1023.         );
  1024.         $weeklyOffer $poRepository->getDefaultOrCustomByCycle(
  1025.             $product,
  1026.             ProductOfferEnum::CYCLE_WEEKLY,
  1027.             $offerHash
  1028.         );
  1029.         $biweeklyOffer $poRepository->getDefaultOrCustomByCycle(
  1030.             $product,
  1031.             ProductOfferEnum::CYCLE_BIWEEKLY,
  1032.             $offerHash
  1033.         );
  1034.         $productOffers array_filter([
  1035.             $monthOffer,
  1036.             $quarterlyOffer,
  1037.             $semiannualOffer,
  1038.             $yearlyOffer,
  1039.             $biennialOffer,
  1040.             $triennialOffer,
  1041.             $weeklyOffer,
  1042.             $biweeklyOffer,
  1043.         ]);
  1044.         $productOffer $poRepository->returnProductOfferOrProductNextPlan(
  1045.             $productOffer
  1046.             $productOffers
  1047.         );
  1048.         foreach ($productOffers as $key => $productOfferCycle) {
  1049.             if($productOfferCycle->getPlanCycle() == $productOffer->getPlanCycle()){
  1050.                 $productOffers[$key] = $productOffer;
  1051.             }
  1052.         }
  1053.         $productPage $productOffer->getProductPage();
  1054.         if(!empty($pageId)){
  1055.             $productPage $this->em->getRepository(ProductPage::class)->find($pageId);
  1056.         }
  1057.         if(!$productPage){
  1058.             return $this->redirectToRoute('notFound');
  1059.         }
  1060.         $externalPage $productPage->getExternalPage();
  1061.         $externalPageLink $productPage->getExternalPageLink();
  1062.         if($externalPage == ProductEnum::YES && !empty($externalPageLink)){
  1063.             return $this->redirect($externalPageLink301);
  1064.         }
  1065.         $this->data['productPage'] = $productPage;
  1066.         $this->data['formName'] = "formFastUserRegister";
  1067.         $this->data["productOffer"] = $productOffer;
  1068.         $this->data['accessPeriod'] = null;
  1069.         $this->data['support'] = CourseEnum::NO;
  1070.         $this->data['supportPeriod'] = null;
  1071.         $this->data['lifetimePeriod'] = CourseEnum::NO;
  1072.         $this->data['certificate'] = CourseEnum::NO;
  1073.         $this->data['generateCertificate'] = CourseCertificateEnum::NO;
  1074.         $this->data['lessonModules'] = [];
  1075.         $this->data['couponKey'] = $couponKey;
  1076.         $this->data['couponKeyValid'] = false;
  1077.         $this->data['productCoupon'] = null;
  1078.         $productRepository $this->em->getRepository(Product::class);
  1079.         $productRepository->saveProductInCache($product);
  1080.         $pcRepository $this->em->getRepository(ProductCoupon::class);
  1081.         $this->data['productOfferCouponTotal'] = $pcRepository->countPublicCouponByProductOffer(
  1082.             $productOffer
  1083.         );
  1084.         if(!empty($couponKey)){
  1085.             foreach ($productOffers as $key => $productOfferCycle) {
  1086.                 $productCoupon $pcRepository->findValidProductCouponByProductOffer(
  1087.                     $couponKey,
  1088.                     $productOfferCycle
  1089.                 );
  1090.                 if($productCoupon){
  1091.                     $amount $productOfferCycle->getPriceReal();
  1092.                     $amount $pcRepository->applyDiscount($productCoupon$amount);
  1093.                     if($amount 0){
  1094.                         $this->data['couponKeyValid'] = true;
  1095.                         if($productOfferCycle->getPlanCycle() == $productOffer->getPlanCycle()){
  1096.                             $productOffer->setPriceRealCopy($amount);
  1097.                             $this->data['productCoupon'] = $productCoupon;
  1098.                         }
  1099.                         $productOfferCycle->setPriceRealCopy($amount);
  1100.                     }
  1101.                 }
  1102.             }
  1103.         }
  1104.         $psRepository $this->em->getRepository(ProductSuggestion::class);
  1105.         $productOfferSuggestions $psRepository->getProductSuggestionsByOfferOrigin(
  1106.             $productOffer,
  1107.             ProductSuggestionEnum::EXECUTE_IN_PRODUCT_PAGE
  1108.         );
  1109.         $productOfferSuggestionsAddCart $psRepository->getProductSuggestionsByOfferOrigin(
  1110.             $productOffer,
  1111.             ProductSuggestionEnum::EXECUTE_ON_ADD_CART
  1112.         );
  1113.         $this->data['productOfferSuggestions'] = $productOfferSuggestions;
  1114.         $this->data['emptyProductSuggestion'] = true;
  1115.         if(!empty($productOfferSuggestions) || !empty($productOfferSuggestionsAddCart)){
  1116.             $this->data['emptyProductSuggestion'] = false;
  1117.         }
  1118.         $numberUtil $this->generalService->getUtil('NumberUtil');
  1119.         $parcelInfo $numberUtil->getNumberMaxParcel(
  1120.             $productOffer->getPriceRealCopy(true),
  1121.             $poRepository->getInstallmentNumberMax($productOffer),
  1122.             $poRepository->getFreeInstallment($productOffer),
  1123.             $productOffer->getSaleOption(),
  1124.             $productOffer->getTypeCheckout(),
  1125.             false
  1126.         );
  1127.         $this->data["productOffers"] = $productOffers;
  1128.         $this->data['parcelInfo'] = $parcelInfo;
  1129.         $this->data['useCard'] = $poRepository->produtOfferAllowCard($productOffer);
  1130.         $this->data['useBill'] = $poRepository->produtOfferAllowBill($productOffer);
  1131.         $this->data['usePix'] = $poRepository->produtOfferAllowPix($productOffer);
  1132.         //ProductOffer Related
  1133.         $productOffersRelateds $poRepository->getProductRelatedOffers(
  1134.             $product
  1135.         );
  1136.         
  1137.         //Permission to view draft page
  1138.         if($product->getStatus() == ProductEnum::DRAFT){
  1139.             $this->checkUserSession($request);
  1140.             $permission $this->userPermissionUtil->getPermission("product""see");
  1141.             if($this->userPermissionUtil->isLow($permission)){
  1142.                 return $this->redirectToRoute('notFound');
  1143.             }
  1144.             $isInTeam $this->em->getRepository(ProductTeam::class)->userExistInProductTeam(
  1145.                 $product,
  1146.                 $this->user
  1147.             );
  1148.             if(!$isInTeam && $this->userPermissionUtil->isMiddle($permission)){
  1149.                 return $this->redirectToRoute('notFound');
  1150.             }
  1151.         }
  1152.         $this->data['product'] = $product;
  1153.         //FAQ
  1154.         $this->data['faqs'] = $this->em->getRepository(Faq::class)->getFaqForProductDetail(
  1155.             $product
  1156.         );
  1157.         //Course Team
  1158.         $teachers $this->em->getRepository(User::class)->getUserTeachersFromProduct(
  1159.             $product
  1160.         );
  1161.         //Product total
  1162.         $this->data['courseTotal'] = $courseRepository->getPublishedCourseNumberByProduct(
  1163.             $product->getId()
  1164.         );
  1165.         $this->data['teacherSection'] = (object)[
  1166.             "teachers" => $teachers,
  1167.             "isCenterTitle" => false,
  1168.             "title" => $this->configuration->getLanguage('instructors''product'),
  1169.             "showSubtitle" => false,
  1170.             "subtitle" => '',
  1171.             "showBtnToAll" => false,
  1172.         ];
  1173.         $this->data['productOffersRelatedsSection'] = (object)[
  1174.             "title" => $this->configuration->getLanguage('related_courses''product'),
  1175.             "subtitle" => $this->configuration->getLanguage('extend_your_knowledge''product'),
  1176.             "name" => "product-related",
  1177.             "items" => $productOffersRelateds,
  1178.             "background" => true,
  1179.             "expand" => false,
  1180.             "slider" => true,
  1181.         ];
  1182.         $this->data['planCoursesSection'] = (object)[
  1183.             "title" => $this->configuration->getLanguage('courses_included_plan''product'),
  1184.             "subtitle" => "",
  1185.             "name" => "product-plan-course",
  1186.             "items" => $courses,
  1187.             "background" => true,
  1188.             "expand" => false,
  1189.             "slider" => false,
  1190.             "isCourse" => true,
  1191.             "itemsTotal" => $this->data['courseTotal']
  1192.         ];
  1193.         $this->data['productOffersSubscriptionSection'] = (object)[
  1194.             "title" => $this->configuration->getLanguage('you_can_expand''product'),
  1195.             "subtitle" => $this->configuration->getLanguage('sign_up_for_a_plan''product'),
  1196.             "name" => "product-subscription-course",
  1197.             "items" => [],
  1198.             "background" => true,
  1199.             "expand" => false,
  1200.             "slider" => false,
  1201.             "isCourse" => true,
  1202.             "itemsTotal" => $this->data['courseTotal']
  1203.         ];
  1204.         $courseTestimonialRepository $this->em->getRepository(CourseTestimonial::class);
  1205.         //Course Stars
  1206.         $this->data['scoreProduct'] = $courseTestimonialRepository->getScoreByProduct(
  1207.             $product
  1208.         );
  1209.         $this->data['scoreProduct']->splitScore = [
  1210.             $this->data['scoreProduct']->fiveStar,
  1211.             $this->data['scoreProduct']->fourStar,
  1212.             $this->data['scoreProduct']->threeStar,
  1213.             $this->data['scoreProduct']->twoStar,
  1214.             $this->data['scoreProduct']->oneStar ,
  1215.         ];
  1216.         //Course Testimonials
  1217.         $this->data['courseTestimonials'] = $courseTestimonialRepository->getTestimonialApprovedRandom(
  1218.             $this->testimonialLimit,
  1219.             $product
  1220.         );
  1221.         foreach ($this->data['courseTestimonials'] as $key => $value) {
  1222.             
  1223.             $value['testimonial'] = StringUtil::encodeStringStatic($value['testimonial']);
  1224.             $value['userName'] = StringUtil::encodeStringStatic($value['userName']);
  1225.             $this->data['courseTestimonials'][$key] = $value;
  1226.         }
  1227.         
  1228.         //Lesson Module Total
  1229.         $lessonModuleRepository $this->em->getRepository(LessonModule::class);
  1230.         $this->data['lessonModuleTotal'] = $lessonModuleRepository->getLessonModuleNumberByProduct(
  1231.             $product
  1232.         );
  1233.         //Lesson Total
  1234.         $lessonRepository $this->em->getRepository(Lesson::class);
  1235.         $this->data['lessonTotal'] = $lessonRepository->getLessonNumberByProduct(
  1236.             $product
  1237.         );
  1238.         $dateLastUpdate null;
  1239.         $auxCourses = [];
  1240.         foreach ($courses as $key => $course) {
  1241.             if($course->getStatus() == CourseEnum::PUBLISHED){
  1242.                 $lastUpdate $course->getDateUpdate();
  1243.                 if(empty($dateLastUpdate) || $lastUpdate $dateLastUpdate){
  1244.                     $dateLastUpdate $lastUpdate;
  1245.                 }
  1246.                 if($course->getCertificate() == CourseEnum::YES){
  1247.                     $this->data['certificate'] = CourseEnum::YES;
  1248.                 }
  1249.                 $auxCourses[] = $course;
  1250.             }
  1251.         }
  1252.         $this->data['dateLastUpdate'] = $dateLastUpdate;
  1253.         
  1254.         //Courses
  1255.         $this->data['courses'] = $auxCourses;
  1256.         $this->data['accessPeriod'] = 0;
  1257.         $this->data['supportPeriod'] = 0;
  1258.         $this->data['lifetimePeriod'] = CourseEnum::NO;
  1259.         $this->data['enrollmentTotal'] = 0;
  1260.         //User Subscription total
  1261.         $userSubscriptionRepository $this->em->getRepository(UserSubscription::class);
  1262.         $this->data['userSubscriptionTotal'] = $userSubscriptionRepository->getUserSubscriptionActiveNumberByProduct(
  1263.             $product
  1264.         );
  1265.         $this->data['keyCaptcha'] = $this->createCaptchaKey($request);
  1266.         //Product time total
  1267.         $this->data['timeTotal'] = $courseRepository->getAllCourseTimeByProduct(
  1268.             $product->getId()
  1269.         );
  1270.         //Sale number limit
  1271.         $poRepository $this->em->getRepository(ProductOffer::class);
  1272.         $this->data['saleLimitRemaining'] = $poRepository->getProductOfferSaleLimitRemaining($productOffer);
  1273.         //Product files total
  1274.         $lessonXLibraryRepository $this->em->getRepository(LessonXLibrary::class);
  1275.         $this->data['fileTotal'] = $lessonXLibraryRepository->getLessonXLibraryFilesByProduct(
  1276.             $product
  1277.         );
  1278.         if($this->user){
  1279.             $marketingService $this->generalService->getService(
  1280.                 'Marketing\\MarketingService'
  1281.             );
  1282.             $marketingService->setTag(TagsMarketingEnum::TAG_VISITED_PAGE);
  1283.             $marketingService->setTextComplement($product->getTitle());
  1284.             $marketingService->setUser($this->user);
  1285.             $marketingService->setProductOffer($productOffer);
  1286.             $marketingService->setOpportunity(ProductOpportunityEnum::TAG_VISITED_PAGE);
  1287.             $marketingService->send();
  1288.         }
  1289.         $pagarMeTransaction $this->generalService->getService(
  1290.             'PagarMe\\PagarMeTransaction'
  1291.         );
  1292.         $paymentConfig $this->configuration->getPaymentConfig();
  1293.         $installmentsOptions $pagarMeTransaction->calculateInstallments([
  1294.             'amount' => $productOffer->getPriceRealCopy(true),
  1295.             'free_installments' => $poRepository->getFreeInstallment($productOffer),
  1296.             'max_installments' => $parcelInfo->maxInstallments,
  1297.             'interest_rate' => $paymentConfig->installmentInterest
  1298.         ]);
  1299.         $this->data['installmentsOptions'] = (array)$installmentsOptions;
  1300.         $userCards null;
  1301.         $userCheckoutInfos null;
  1302.         if($this->user){
  1303.             $userCardRepository $this->em->getRepository(UserCard::class);
  1304.             $userCards $userCardRepository->findBy([
  1305.                 "user" => $this->user->getId(),
  1306.                 "deleted" => UserCardEnum::ITEM_NO_DELETED
  1307.             ]);
  1308.             $userCheckoutInfoRepository $this->em->getRepository(UserCheckoutInfo::class);
  1309.             $userCheckoutInfos $userCheckoutInfoRepository->findBy([
  1310.                 "user" => $this->user->getId(),
  1311.                 "deleted" => UserCheckoutInfoEnum::ITEM_NO_DELETED
  1312.             ], [ "default" => "DESC" ]);
  1313.         }
  1314.         $this->data["isOnSale"] = $poRepository->checkProductOfferIsOnSale($productOffer);
  1315.         $this->data["userCards"] = $userCards;
  1316.         $this->data["userCheckoutInfos"] = $userCheckoutInfos;
  1317.         $credentials null;
  1318.         $videoLibrary $productPage->getLibrary();
  1319.         if($videoLibrary){
  1320.             $libraryRepository $this->em->getRepository(Library::class);
  1321.             $credentials $libraryRepository->getVideoCredentials($videoLibrary);
  1322.         }
  1323.         $this->data["credentials"] = $credentials;
  1324.         if($productPage->getType() == ProductPageEnum::TYPE_LAND_PAGE){
  1325.             $pixelService $this->generalService->getService('Marketing\\PixelService');
  1326.             $pixelService->sendConversion('AddToCart', (object)[
  1327.                 "content_ids" => [ $productOffer->getId() ],
  1328.                 "content_name" => $productOffer->getTitle(),
  1329.                 "currency" => $productOffer->getCurrencyCode(),
  1330.                 "value" => $productOffer->getPriceReal(),
  1331.             ]);
  1332.             return $this->renderEAD('product/landingpage/index.html.twig');
  1333.         }
  1334.         return $this->renderEAD("product/product-detail.html.twig");
  1335.     }
  1336.     /**
  1337.      * @Route(
  1338.      *      path          = "/{type}/{slug}/{offerHash}",
  1339.      *      name          = "productDetailCombo",
  1340.      *      methods       = {"GET"},
  1341.      *      defaults      = { "offerHash": null },
  1342.      *      requirements  = {"type"="combo"}
  1343.      * )
  1344.      */
  1345.     public function getProductComboDetailPage(Request $request) {
  1346.         $this->requestUtil->setRequest($request)->setData();
  1347.         $utmsUrl http_build_query($this->requestUtil->getData());   
  1348.         $this->data['utmsUrl'] = $utmsUrl;
  1349.         
  1350.         $slug $request->get('slug');
  1351.         $type $request->get('type');
  1352.         $offerHash $request->get('offerHash');
  1353.         $couponKey $request->get('coupon');
  1354.         $pageId $request->get('page');
  1355.         $productType ProductEnum::COMBO;
  1356.         $poRepository $this->em->getRepository(ProductOffer::class);
  1357.         $productOffer $poRepository->getProductBySlug(
  1358.             $slug,
  1359.             $productType,
  1360.             $offerHash
  1361.         );
  1362.         if(!$productOffer){
  1363.             $productOffer $poRepository->getProductBySlug(
  1364.                 $slug,
  1365.                 $productType
  1366.             );
  1367.             $couponKey $offerHash;
  1368.             
  1369.             if(!$productOffer){
  1370.                 return $this->redirectToRoute('notFound');
  1371.             }
  1372.         }
  1373.         $product $productOffer->getProduct();
  1374.         if($product->getType() != $productType){
  1375.             return $this->redirectToRoute('notFound');
  1376.         }
  1377.         $productOffer $poRepository->returnProductOfferOrProductNextClean($productOffer);
  1378.         
  1379.         $productPage $productOffer->getProductPage();
  1380.         if(!empty($pageId)){
  1381.             $productPage $this->em->getRepository(ProductPage::class)->find($pageId);
  1382.         }
  1383.         if(!$productPage){
  1384.             return $this->redirectToRoute('notFound');
  1385.         }
  1386.         
  1387.         $externalPage $productPage->getExternalPage();
  1388.         $externalPageLink $productPage->getExternalPageLink();
  1389.         if($externalPage == ProductEnum::YES && !empty($externalPageLink)){
  1390.             return $this->redirect($externalPageLink301);
  1391.         }
  1392.         $this->data['productPage'] = $productPage;
  1393.         $productRelateds $product->getProductRelated();
  1394.         $courseRepository $this->em->getRepository(Course::class);
  1395.         $courses $courseRepository->getCoursesByProduct($product->getId());
  1396.         $this->data['couponKey'] = $couponKey;
  1397.         $this->data['couponKeyValid'] = false;
  1398.         $this->data['productCoupon'] = null;
  1399.         $productRepository $this->em->getRepository(Product::class);
  1400.         $productRepository->saveProductInCache($product);
  1401.         
  1402.         $pcRepository $this->em->getRepository(ProductCoupon::class);
  1403.         $this->data['productOfferCouponTotal'] = $pcRepository->countPublicCouponByProductOffer(
  1404.             $productOffer
  1405.         );
  1406.         $this->data['certificate'] = CourseEnum::NO;
  1407.         $this->data['generateCertificate'] = CourseCertificateEnum::NO;
  1408.         
  1409.         if(!empty($couponKey)){
  1410.             $productCoupon $pcRepository->findValidProductCouponByProductOffer(
  1411.                 $couponKey,
  1412.                 $productOffer
  1413.             );
  1414.             if($productCoupon){
  1415.                 $amount $productOffer->getPriceReal();
  1416.                 $amount $pcRepository->applyDiscount($productCoupon$amount);
  1417.                 if($amount 0){
  1418.                     $this->data['couponKeyValid'] = true;
  1419.                     $this->data['productCoupon'] = $productCoupon;
  1420.                     $productOffer->setPriceRealCopy($amount);
  1421.                 }else{
  1422.                     if($this->user){
  1423.                         $productCoupon->setUsageNumber($productCoupon->getUsageNumber() + 1);
  1424.                         $this->em->flush();
  1425.                         $enrollmentService $this->generalService->getService(
  1426.                             'EnrollmentService'
  1427.                         );
  1428.     
  1429.                         $enrollmentService->setOrigin(EnrollmentEnum::ORIGIN_COUPOM);
  1430.                         $enrollmentService->setCouponKey($couponKey);
  1431.                         $enrollmentService->enrollUserByProduct(
  1432.                             $this->user,
  1433.                             $productOffer->getProduct()
  1434.                         );
  1435.                     }else{
  1436.                         $params = [
  1437.                             "poID" => $productOffer->getId(),
  1438.                             "pcID" => $productCoupon->getId(),
  1439.                         ];
  1440.                         return $this->redirectToRoute('cartAdd'$params);
  1441.                     }
  1442.                 }
  1443.             }
  1444.         }
  1445.         $numberUtil $this->generalService->getUtil('NumberUtil');
  1446.         $parcelInfo $numberUtil->getNumberMaxParcel(
  1447.             $productOffer->getPriceRealCopy(true),
  1448.             $poRepository->getInstallmentNumberMax($productOffer),
  1449.             $poRepository->getFreeInstallment($productOffer),
  1450.             $productOffer->getSaleOption(),
  1451.             $productOffer->getTypeCheckout(),
  1452.             false
  1453.         );
  1454.         $this->data['parcelInfo'] = $parcelInfo;
  1455.         $this->data['useCard'] = $poRepository->produtOfferAllowCard($productOffer);
  1456.         $this->data['useBill'] = $poRepository->produtOfferAllowBill($productOffer);
  1457.         $this->data['usePix'] = $poRepository->produtOfferAllowPix($productOffer);
  1458.         
  1459.         //ProductOffer Related
  1460.         $productOffersRelateds $poRepository->getProductRelatedOffers(
  1461.             $product
  1462.         );
  1463.         
  1464.         //Permission to view draft page
  1465.         if(
  1466.             $productOffer->getStatus() == ProductOfferEnum::DRAFT || 
  1467.             $product->getStatus() == ProductEnum::DRAFT
  1468.         ){
  1469.             $this->checkUserSession($request);
  1470.             $permission $this->userPermissionUtil->getPermission("product""see");
  1471.             if($this->userPermissionUtil->isLow($permission)){
  1472.                 return $this->redirectToRoute('notFound');
  1473.             }
  1474.             $isInTeam $this->em->getRepository(ProductTeam::class)->userExistInProductTeam(
  1475.                 $product,
  1476.                 $this->user
  1477.             );
  1478.             if(!$isInTeam && $this->userPermissionUtil->isMiddle($permission)){
  1479.                 return $this->redirectToRoute('notFound');
  1480.             }
  1481.         }
  1482.         $this->data['productOffer'] = $productOffer;
  1483.         $this->data['product'] = $product;
  1484.         $psRepository $this->em->getRepository(ProductSuggestion::class);
  1485.         $productOfferSuggestions $psRepository->getProductSuggestionsByOfferOrigin(
  1486.             $productOffer,
  1487.             ProductSuggestionEnum::EXECUTE_IN_PRODUCT_PAGE
  1488.         );
  1489.         $productOfferSuggestionsAddCart $psRepository->getProductSuggestionsByOfferOrigin(
  1490.             $productOffer,
  1491.             ProductSuggestionEnum::EXECUTE_ON_ADD_CART
  1492.         );
  1493.         $this->data['productOfferSuggestions'] = $productOfferSuggestions;
  1494.         $this->data['emptyProductSuggestion'] = true;
  1495.         if(!empty($productOfferSuggestions) || !empty($productOfferSuggestionsAddCart)){
  1496.             $this->data['emptyProductSuggestion'] = false;
  1497.         }
  1498.         
  1499.         //FAQ
  1500.         $this->data['faqs'] = $this->em->getRepository(Faq::class)->getFaqForProductDetail(
  1501.             $product
  1502.         );
  1503.         //Course Team
  1504.         $teachers $this->em->getRepository(User::class)->getUserTeachersFromProduct(
  1505.             $product
  1506.         );
  1507.         //Product total
  1508.         $this->data['courseTotal'] = $courseRepository->getPublishedCourseNumberByProduct(
  1509.             $product->getId()
  1510.         );
  1511.         $this->data['formName'] = "formFastUserRegister";
  1512.         $this->data['teacherSection'] = (object)[
  1513.             "teachers" => $teachers,
  1514.             "isCenterTitle" => false,
  1515.             "title" => $this->configuration->getLanguage('instructors''product'),
  1516.             "showSubtitle" => false,
  1517.             "subtitle" => '',
  1518.             "showBtnToAll" => false,
  1519.         ];
  1520.         $this->data['productOffersRelatedsSection'] = (object)[
  1521.             "title" => $this->configuration->getLanguage('related_courses''product'),
  1522.             "subtitle" => $this->configuration->getLanguage('extend_your_knowledge''product'),
  1523.             "name" => "product-related",
  1524.             "items" => $productOffersRelateds,
  1525.             "background" => true,
  1526.             "expand" => false,
  1527.             "slider" => true,
  1528.         ];
  1529.         $this->data['planCoursesSection'] = (object)[
  1530.             "title" => $this->configuration->getLanguage('courses_included_combo''product'),
  1531.             "subtitle" => "",
  1532.             "name" => "product-plan-course",
  1533.             "items" => $courses,
  1534.             "background" => true,
  1535.             "expand" => false,
  1536.             "slider" => false,
  1537.             "isCourse" => true,
  1538.             "itemsTotal" => $this->data['courseTotal'],
  1539.         ];
  1540.         $this->data['productOffersSubscriptionSection'] = (object)[
  1541.             "title" => $this->configuration->getLanguage('you_can_expand''product'),
  1542.             "subtitle" => $this->configuration->getLanguage('sign_up_for_a_plan''product'),
  1543.             "name" => "product-subscription-course",
  1544.             "items" => [],
  1545.             "background" => true,
  1546.             "expand" => false,
  1547.             "slider" => false,
  1548.             "isCourse" => true,
  1549.             "itemsTotal" => $this->data['courseTotal']
  1550.         ];
  1551.         $courseTestimonialRepository $this->em->getRepository(CourseTestimonial::class);
  1552.         //Course Stars
  1553.         $this->data['scoreProduct'] = $courseTestimonialRepository->getScoreByProduct(
  1554.             $product
  1555.         );
  1556.         $this->data['scoreProduct']->splitScore = [
  1557.             $this->data['scoreProduct']->fiveStar,
  1558.             $this->data['scoreProduct']->fourStar,
  1559.             $this->data['scoreProduct']->threeStar,
  1560.             $this->data['scoreProduct']->twoStar,
  1561.             $this->data['scoreProduct']->oneStar ,
  1562.         ];
  1563.         //Course Testimonials
  1564.         $this->data['courseTestimonials'] = $courseTestimonialRepository->getTestimonialApprovedRandom(
  1565.             $this->testimonialLimit,
  1566.             $product
  1567.         );
  1568.         foreach ($this->data['courseTestimonials'] as $key => $value) {
  1569.             
  1570.             $value['testimonial'] = StringUtil::encodeStringStatic($value['testimonial']);
  1571.             $value['userName'] = StringUtil::encodeStringStatic($value['userName']);
  1572.             $this->data['courseTestimonials'][$key] = $value;
  1573.         }
  1574.         
  1575.         //Lesson Module Total
  1576.         $lessonModuleRepository $this->em->getRepository(LessonModule::class);
  1577.         $this->data['lessonModuleTotal'] = $lessonModuleRepository->getLessonModuleNumberByProduct(
  1578.             $product
  1579.         );
  1580.         //Lesson Total
  1581.         $lessonRepository $this->em->getRepository(Lesson::class);
  1582.         $this->data['lessonTotal'] = $lessonRepository->getLessonNumberByProduct(
  1583.             $product
  1584.         );
  1585.         $dateLastUpdate null;
  1586.         $auxCourses = [];
  1587.         foreach ($courses as $key => $course) {
  1588.             if($course->getStatus() == CourseEnum::PUBLISHED){
  1589.                 $lastUpdate $course->getDateUpdate();
  1590.                 if(empty($dateLastUpdate) || $lastUpdate $dateLastUpdate){
  1591.                     $dateLastUpdate $lastUpdate;
  1592.                 }
  1593.                 if($course->getCertificate() == CourseEnum::YES){
  1594.                     $this->data['certificate'] = CourseEnum::YES;
  1595.                 }
  1596.                 $auxCourses[] = $course;
  1597.             }
  1598.         }
  1599.         $this->data['dateLastUpdate'] = $dateLastUpdate;
  1600.         
  1601.         //Courses
  1602.         $this->data['courses'] = $auxCourses;
  1603.         $this->data['support'] = CourseEnum::NO;
  1604.         $this->data['enrollmentTotal'] = 0;
  1605.         $this->data['userSubscriptionTotal'] = 0;
  1606.         $this->data['accessPeriod'] = 0;
  1607.         $this->data['supportPeriod'] = 0;
  1608.         $this->data['lifetimePeriod'] = CourseEnum::NO;
  1609.         $this->data['lessonModules'] = [];
  1610.         //Sale number limit
  1611.         $poRepository $this->em->getRepository(ProductOffer::class);
  1612.         $this->data['saleLimitRemaining'] = $poRepository->getProductOfferSaleLimitRemaining($productOffer);
  1613.         //Product time total
  1614.         $this->data['timeTotal'] = $courseRepository->getAllCourseTimeByProduct(
  1615.             $product->getId()
  1616.         );
  1617.         //Product files total
  1618.         $lessonXLibraryRepository $this->em->getRepository(LessonXLibrary::class);
  1619.         $this->data['fileTotal'] = $lessonXLibraryRepository->getLessonXLibraryFilesByProduct(
  1620.             $product
  1621.         );
  1622.         $this->data['keyCaptcha'] = $this->createCaptchaKey($request);
  1623.         if($this->user){
  1624.             $marketingService $this->generalService->getService(
  1625.                 'Marketing\\MarketingService'
  1626.             );
  1627.             $marketingService->setTag(TagsMarketingEnum::TAG_VISITED_PAGE);
  1628.             $marketingService->setTextComplement($product->getTitle());
  1629.             $marketingService->setUser($this->user);
  1630.             $marketingService->setProductOffer($productOffer);
  1631.             $marketingService->setOpportunity(ProductOpportunityEnum::TAG_VISITED_PAGE);
  1632.             $marketingService->send();
  1633.         }
  1634.         $this->data["productOffers"] = [ $productOffer ];
  1635.         $pagarMeTransaction $this->generalService->getService(
  1636.             'PagarMe\\PagarMeTransaction'
  1637.         );
  1638.         $paymentConfig $this->configuration->getPaymentConfig();
  1639.         $installmentsOptions $pagarMeTransaction->calculateInstallments([
  1640.             'amount' => $productOffer->getPriceRealCopy(true),
  1641.             'free_installments' => $poRepository->getFreeInstallment($productOffer),
  1642.             'max_installments' => $parcelInfo->maxInstallments,
  1643.             'interest_rate' => $paymentConfig->installmentInterest
  1644.         ]);
  1645.         $this->data['installmentsOptions'] = (array)$installmentsOptions;
  1646.         $userCards null;
  1647.         $userCheckoutInfos null;
  1648.         if($this->user){
  1649.             $userCardRepository $this->em->getRepository(UserCard::class);
  1650.             $userCards $userCardRepository->findBy([
  1651.                 "user" => $this->user->getId(),
  1652.                 "deleted" => UserCardEnum::ITEM_NO_DELETED
  1653.             ]);
  1654.             $userCheckoutInfoRepository $this->em->getRepository(UserCheckoutInfo::class);
  1655.             $userCheckoutInfos $userCheckoutInfoRepository->findBy([
  1656.                 "user" => $this->user->getId(),
  1657.                 "deleted" => UserCheckoutInfoEnum::ITEM_NO_DELETED
  1658.             ], [ "default" => "DESC" ]);
  1659.         }
  1660.         $this->data["isOnSale"] = $poRepository->checkProductOfferIsOnSale($productOffer);
  1661.         $this->data["userCards"] = $userCards;
  1662.         $this->data["userCheckoutInfos"] = $userCheckoutInfos;
  1663.         $credentials null;
  1664.         $videoLibrary $productPage->getLibrary();
  1665.         if($videoLibrary){
  1666.             $libraryRepository $this->em->getRepository(Library::class);
  1667.             $credentials $libraryRepository->getVideoCredentials($videoLibrary);
  1668.         }
  1669.         $this->data["credentials"] = $credentials;
  1670.         if($productPage->getType() == ProductPageEnum::TYPE_LAND_PAGE){
  1671.             if($this->user && $productOffer->getSaleOption() == ProductOfferEnum::FREE){
  1672.                 $enrollmentService $this->generalService->getService(
  1673.                     'EnrollmentService'
  1674.                 );
  1675.                 $enrollmentService->setOrigin(EnrollmentEnum::ORIGIN_FREE);
  1676.                 $enrollmentService->enrollUserByProduct(
  1677.                     $this->user,
  1678.                     $productOffer->getProduct()
  1679.                 );
  1680.             }
  1681.             $pixelService $this->generalService->getService('Marketing\\PixelService');
  1682.             $pixelService->sendConversion('AddToCart', (object)[
  1683.                 "content_ids" => [ $productOffer->getId() ],
  1684.                 "content_name" => $productOffer->getTitle(),
  1685.                 "currency" => $productOffer->getCurrencyCode(),
  1686.                 "value" => $productOffer->getPriceReal(),
  1687.             ]);
  1688.             
  1689.             return $this->renderEAD('product/landingpage/index.html.twig');
  1690.         }
  1691.         return $this->renderEAD("product/product-detail.html.twig");
  1692.     }
  1693. }