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) && $this->user){
  548.             $permission $this->userPermissionUtil->getPermission("product""see");
  549.             if(!$this->userPermissionUtil->isLow($permission)){
  550.                 $productPage $this->em->getRepository(ProductPage::class)->find($pageId);
  551.             }
  552.         }
  553.         if(!$productPage){
  554.             return $this->redirectToRoute('notFound');
  555.         }
  556.         $externalPage $productPage->getExternalPage();
  557.         $externalPageLink $productPage->getExternalPageLink();
  558.         if($externalPage == ProductEnum::YES && !empty($externalPageLink)){
  559.             return $this->redirect($externalPageLink301);
  560.         }
  561.         $this->data['productPage'] = $productPage;
  562.         $productRelateds $product->getProductRelated();
  563.         $courseRepository $this->em->getRepository(Course::class);
  564.         $courses $courseRepository->getCoursesByProduct($product->getId());
  565.         $this->data['formName'] = "formFastUserRegister";
  566.         $this->data['accessPeriod'] = null;
  567.         $this->data['lifetimePeriod'] = CourseEnum::NO;
  568.         $this->data['support'] = CourseEnum::NO;
  569.         $this->data['supportPeriod'] = null;
  570.         $this->data['lifetimeSupport'] = CourseEnum::NO;
  571.         $this->data['certificate'] = CourseEnum::NO;
  572.         $this->data['generateCertificate'] = CourseCertificateEnum::NO;
  573.         $this->data['lessonModules'] = [];
  574.         $this->data['couponKey'] = $couponKey;
  575.         $this->data['couponKeyValid'] = false;
  576.         $this->data['productCoupon'] = null;
  577.         $hasModule $this->configuration->isModuleActive("product_coupon_module");
  578.         $enrollmentService $this->generalService->getService('EnrollmentService');
  579.         $productRepository $this->em->getRepository(Product::class);
  580.         $productRepository->saveProductInCache($product);
  581.         $pcRepository $this->em->getRepository(ProductCoupon::class);
  582.         $this->data['productOfferCouponTotal'] = $pcRepository->countPublicCouponByProductOffer(
  583.             $productOffer
  584.         );
  585.         if(!empty($couponKey) && $hasModule){
  586.             $productCoupon $pcRepository->findValidProductCouponByProductOffer(
  587.                 $couponKey,
  588.                 $productOffer
  589.             );
  590.             if($productCoupon){
  591.                 $amount $productOffer->getPriceReal();
  592.                 $amount $pcRepository->applyDiscount($productCoupon$amount);
  593.                 if($amount 0){
  594.                     $this->data['productCoupon'] = $productCoupon;
  595.                     $this->data['couponKeyValid'] = true;
  596.                     $productOffer->setPriceRealCopy($amount);
  597.  
  598.                 }else{
  599.                     if($this->user){
  600.                         $productCoupon->setUsageNumber(
  601.                             $productCoupon->getUsageNumber() + 1
  602.                         );
  603.                         $this->em->flush();
  604.                         $enrollmentService->setOrigin(EnrollmentEnum::ORIGIN_COUPOM);
  605.                         $enrollmentService->setCouponKey($couponKey);
  606.                         $enrollmentService->enrollUserByProduct(
  607.                             $this->user,
  608.                             $productOffer->getProduct()
  609.                         );
  610.                     }else{
  611.                         
  612.                         $params = [
  613.                             "poID" => $productOffer->getId(),
  614.                             "pcID" => $productCoupon->getId(),
  615.                         ];
  616.                         return $this->redirectToRoute('cartAdd'$params);
  617.                     }
  618.                 }
  619.             }
  620.         }
  621.        
  622.         $psRepository $this->em->getRepository(ProductSuggestion::class);
  623.         $productOfferSuggestions $psRepository->getProductSuggestionsByOfferOrigin(
  624.             $productOffer,
  625.             ProductSuggestionEnum::EXECUTE_IN_PRODUCT_PAGE
  626.         );
  627.         $productOfferSuggestionsAddCart $psRepository->getProductSuggestionsByOfferOrigin(
  628.             $productOffer,
  629.             ProductSuggestionEnum::EXECUTE_ON_ADD_CART
  630.         );
  631.         $this->data['emptyProductSuggestion'] = true;
  632.         if(!empty($productOfferSuggestions) || !empty($productOfferSuggestionsAddCart)){
  633.             $this->data['emptyProductSuggestion'] = false;
  634.         }
  635.         if($this->data['productCoupon'] && $hasModule){
  636.             foreach ($productOfferSuggestions as $key => $offerSuggestion) {
  637.                 $pcSuggestion $pcRepository->findValidProductCouponByIdAndProductOffer(
  638.                     $this->data['productCoupon']->getId(), 
  639.                     $offerSuggestion,
  640.                     true
  641.                 );
  642.                 if($pcSuggestion){
  643.                     $amount $offerSuggestion->getPriceReal();
  644.                     $amount $pcRepository->applyDiscount($pcSuggestion$amount);
  645.                     if($amount 0){
  646.                         $offerSuggestion->setPriceRealCopy($amount);
  647.                     }else{
  648.                         if($this->user){
  649.                             $pcSuggestion->setUsageNumber(
  650.                                 $pcSuggestion->getUsageNumber() + 1
  651.                             );
  652.                             $this->em->flush();
  653.                             $enrollmentService->setOrigin(EnrollmentEnum::ORIGIN_COUPOM);
  654.                             $enrollmentService->setCouponKey($couponKey);
  655.                             $enrollmentService->enrollUserByProduct(
  656.                                 $this->user,
  657.                                 $offerSuggestion->getProduct()
  658.                             );
  659.                         }else{
  660.                             $hash base64_encode($request->getUri());
  661.                             $url $this->generalService->generateUrl('login', [ 
  662.                                 "hash" => $hash 
  663.                             ]);
  664.                             $redirectResponse = new RedirectResponse($url);
  665.                             $redirectResponse->headers->set('Content-Type''text/html');
  666.                             $redirectResponse->send();
  667.                             exit;
  668.                         }
  669.                     }
  670.                 }
  671.                 $productOfferSuggestions[$key] = $offerSuggestion;
  672.             }
  673.         }
  674.         $this->data['productOfferSuggestions'] = $productOfferSuggestions;
  675.         $numberUtil $this->generalService->getUtil('NumberUtil');
  676.         $parcelInfo $numberUtil->getNumberMaxParcel(
  677.             $productOffer->getPriceRealCopy(true),
  678.             $poRepository->getInstallmentNumberMax($productOffer),
  679.             $poRepository->getFreeInstallment($productOffer),
  680.             $productOffer->getSaleOption(),
  681.             $productOffer->getTypeCheckout(),
  682.             false
  683.         );
  684.         $this->data['parcelInfo'] = $parcelInfo;
  685.         $this->data['useCard'] = $poRepository->produtOfferAllowCard($productOffer);
  686.         $this->data['useBill'] = $poRepository->produtOfferAllowBill($productOffer);
  687.         $this->data['usePix'] = $poRepository->produtOfferAllowPix($productOffer);
  688.         //ProductOffer Related
  689.         $productOffersRelateds $poRepository->getProductRelatedOffers(
  690.             $product
  691.         );
  692.         //Permission to view draft page
  693.         if(
  694.             $productOffer->getStatus() == ProductOfferEnum::DRAFT || 
  695.             $product->getStatus() == ProductEnum::DRAFT
  696.         ){
  697.             $this->checkUserSession($request);
  698.             $permission $this->userPermissionUtil->getPermission("product""see");
  699.             if($this->userPermissionUtil->isLow($permission)){
  700.                 return $this->redirectToRoute('notFound');
  701.             }
  702.             $isInTeam $this->em->getRepository(ProductTeam::class)->userExistInProductTeam(
  703.                 $product,
  704.                 $this->user
  705.             );
  706.             if(!$isInTeam && $this->userPermissionUtil->isMiddle($permission)){
  707.                 return $this->redirectToRoute('notFound');
  708.             }
  709.         }
  710.         $this->data['productOffer'] = $productOffer;
  711.         $this->data['product'] = $product;
  712.         //FAQ
  713.         $this->data['faqs'] = $this->em->getRepository(Faq::class)->getFaqForProductDetail(
  714.             $product
  715.         );
  716.         //Course Team
  717.         $teachers $this->em->getRepository(User::class)->getUserTeachersFromProduct(
  718.             $product
  719.         );
  720.         $this->data['courseTotal'] = 0;
  721.         $this->data['courses'] = $courses;
  722.         $this->data['teacherSection'] = (object)[
  723.             "teachers" => $teachers,
  724.             "isCenterTitle" => false,
  725.             "title" => $this->configuration->getLanguage('instructors''product'),
  726.             "showSubtitle" => false,
  727.             "subtitle" => '',
  728.             "showBtnToAll" => false,
  729.         ];
  730.         $this->data['productOffersRelatedsSection'] = (object)[
  731.             "title" => $this->configuration->getLanguage('related_products''product'),
  732.             "subtitle" => $this->configuration->getLanguage('extend_your_knowledge''product'),
  733.             "name" => "product-related",
  734.             "items" => $productOffersRelateds,
  735.             "background" => false,
  736.             "expand" => false,
  737.             "slider" => true,
  738.         ];
  739.         $this->data['planCoursesSection'] = (object)[
  740.             "title" => $this->configuration->getLanguage('courses_included_plan''product'),
  741.             "subtitle" => "",
  742.             "name" => "product-plan-course",
  743.             "items" => $courses,
  744.             "background" => true,
  745.             "expand" => false,
  746.             "slider" => false,
  747.             "isCourse" => true,
  748.             "itemsTotal" => $this->data['courseTotal']
  749.         ];
  750.         $courseTestimonialRepository $this->em->getRepository(CourseTestimonial::class);
  751.         //Course Stars
  752.         $this->data['scoreProduct'] = $courseTestimonialRepository->getScoreByProduct(
  753.             $product
  754.         );
  755.         $this->data['scoreProduct']->splitScore = [
  756.             $this->data['scoreProduct']->fiveStar,
  757.             $this->data['scoreProduct']->fourStar,
  758.             $this->data['scoreProduct']->threeStar,
  759.             $this->data['scoreProduct']->twoStar,
  760.             $this->data['scoreProduct']->oneStar,
  761.         ];
  762.         //Course Testimonials
  763.         $this->data['courseTestimonials'] = $courseTestimonialRepository->getTestimonialApprovedRandom(
  764.             $this->testimonialLimit,
  765.             $product
  766.         );
  767.         foreach ($this->data['courseTestimonials'] as $key => $value) {
  768.             
  769.             $value['testimonial'] = StringUtil::encodeStringStatic($value['testimonial']);
  770.             $value['userName'] = StringUtil::encodeStringStatic($value['userName']);
  771.             $this->data['courseTestimonials'][$key] = $value;
  772.         }
  773.         
  774.         //Lesson Module Total
  775.         $lessonModuleRepository $this->em->getRepository(LessonModule::class);
  776.         $this->data['lessonModuleTotal'] = $lessonModuleRepository->getLessonModuleNumberByProduct(
  777.             $product
  778.         );
  779.         //Lesson Total
  780.         $lessonRepository $this->em->getRepository(Lesson::class);
  781.         $this->data['lessonTotal'] = $lessonRepository->getLessonNumberByProduct(
  782.             $product
  783.         );
  784.         $productOffersSubscriptionAll = [];
  785.         $dateLastUpdate null;
  786.         $auxCourses = [];
  787.         foreach ($courses as $key => $course) {
  788.             if($course->getStatus() == CourseEnum::PUBLISHED){
  789.                 $lastUpdate $course->getDateUpdate();
  790.                 if(empty($dateLastUpdate) || $lastUpdate $dateLastUpdate){
  791.                     $dateLastUpdate $lastUpdate;
  792.                 }
  793.                 if($course->getCertificate() == CourseEnum::YES){
  794.                     $this->data['certificate'] = CourseEnum::YES;
  795.                 }
  796.                 $productOffersSubscription $poRepository->getProductOffersByCourse(
  797.                     $course,
  798.                     ProductEnum::SUBSCRIPTION
  799.                 );
  800.                 $productOffersSubscriptionAll array_merge(
  801.                     $productOffersSubscriptionAll,
  802.                     $productOffersSubscription
  803.                 );
  804.                 $auxCourses[] = $course;
  805.             }
  806.         }
  807.         $this->data['dateLastUpdate'] = $dateLastUpdate;
  808.         $this->data['productOffersSubscriptionSection'] = (object)[
  809.             "title" => $this->configuration->getLanguage('you_can_expand''product'),
  810.             "subtitle" => $this->configuration->getLanguage('sign_up_for_a_plan''product'),
  811.             "name" => "product-subscription-course",
  812.             "items" => $productOffersSubscriptionAll,
  813.             "background" => true,
  814.             "expand" => false,
  815.             "slider" => false,
  816.             "isCourse" => true,
  817.             "itemsTotal" => $this->data['courseTotal']
  818.         ];
  819.         //Sale number limit
  820.         $poRepository $this->em->getRepository(ProductOffer::class);
  821.         $this->data['saleLimitRemaining'] = $poRepository->getProductOfferSaleLimitRemaining(
  822.             $productOffer
  823.         );
  824.         
  825.         //Courses
  826.         $this->data['courses'] = $auxCourses;
  827.         //Product time total
  828.         $this->data['timeTotal'] = $courseRepository->getAllCourseTimeByProduct($product);
  829.         //Product files total
  830.         $lessonXLibraryRepository $this->em->getRepository(LessonXLibrary::class);
  831.         $this->data['fileTotal'] = $lessonXLibraryRepository->getLessonXLibraryFilesByProduct(
  832.             $product
  833.         );
  834.         $this->data['userSubscriptionTotal'] = 0;
  835.         $this->data['enrollmentTotal'] = 0;
  836.         $this->data['keyCaptcha'] = $this->createCaptchaKey($request);
  837.         if(!empty(count($courses))){
  838.             $course $courses[0];
  839.             $enrollmentRepository $this->em->getRepository(Enrollment::class);
  840.             $this->data['enrollmentTotal'] = $enrollmentRepository->countEnrollmentsByCourse(
  841.                 $course->getId(),
  842.                 EnrollmentEnum::STATUS_ACTIVE
  843.             );
  844.             $cycleItemRepository $this->em->getRepository(CycleItem::class);
  845.             $this->data['accessPeriod'] = $course->getSupport();
  846.             $accessPeriod $cycleItemRepository->getPeriodByDay(
  847.                 $course->getAccessPeriod()
  848.             );
  849.             $suportPeriod $cycleItemRepository->getPeriodByDay(
  850.                 $course->getSupportPeriod()
  851.             );
  852.         
  853.             if($accessPeriod){
  854.                 $this->data['accessPeriod'] = $accessPeriod->getName();
  855.             }
  856.             if($suportPeriod){
  857.                 $this->data['supportPeriod'] = $suportPeriod->getName();
  858.             }
  859.             $this->data['lifetimePeriod'] = $course->getLifetimePeriod();
  860.             $this->data['lifetimeSupport'] = $course->getLifetimeSupport();
  861.             
  862.             $this->data['support'] = $course->getSupport();
  863.             //Lesson modules and lessons
  864.             $lessonModules $lessonModuleRepository->getLessonModulesByCourse($course);
  865.             $lessonRepository $this->em->getRepository(Lesson::class);
  866.             
  867.             foreach ($lessonModules as $key => $lessonModule) {
  868.                 $lessonModule->lessons $lessonRepository->getLessonByLessonModule(
  869.                     $lessonModule
  870.                 );
  871.                 $lessonModule->workloads $lessonModuleRepository->getLessonModuleTime(
  872.                     $lessonModule
  873.                 );
  874.             }
  875.             $this->data['lessonModules'] = $lessonModules;
  876.         }
  877.         if($this->user){
  878.             $marketingService $this->generalService->getService(
  879.                 'Marketing\\MarketingService'
  880.             );
  881.             $marketingService->setTag(TagsMarketingEnum::TAG_VISITED_COURSE_PAGE);
  882.             $marketingService->setTextComplement($product->getTitle());
  883.             $marketingService->setUser($this->user);
  884.             $marketingService->setProductOffer($productOffer);
  885.             $marketingService->setOpportunity(ProductOpportunityEnum::TAG_VISITED_COURSE_PAGE);
  886.             $marketingService->send();
  887.         }
  888.         $pagarMeTransaction $this->generalService->getService(
  889.             'PagarMe\\PagarMeTransaction'
  890.         );
  891.         $paymentConfig $this->configuration->getPaymentConfig();
  892.         $installmentsOptions $pagarMeTransaction->calculateInstallments([
  893.             'amount' => $productOffer->getPriceRealCopy(true),
  894.             'free_installments' => $poRepository->getFreeInstallment($productOffer),
  895.             'max_installments' => $parcelInfo->maxInstallments,
  896.             'interest_rate' => $paymentConfig->installmentInterest
  897.         ]);
  898.         $this->data['installmentsOptions'] = (array)$installmentsOptions;
  899.         $userCards null;
  900.         $userCheckoutInfos null;
  901.         if($this->user){
  902.             $userCardRepository $this->em->getRepository(UserCard::class);
  903.             $userCards $userCardRepository->getValidUserCard();
  904.             $userCheckoutInfoRepository $this->em->getRepository(UserCheckoutInfo::class);
  905.             $userCheckoutInfos $userCheckoutInfoRepository->findBy([
  906.                 "user" => $this->user->getId(),
  907.                 "deleted" => UserCheckoutInfoEnum::ITEM_NO_DELETED
  908.             ], [ "default" => "DESC" ]);
  909.         }
  910.         $this->data["isOnSale"] = $poRepository->checkProductOfferIsOnSale($productOffer);
  911.         $this->data["userCards"] = $userCards;
  912.         $this->data["userCheckoutInfos"] = $userCheckoutInfos;
  913.         $this->data["productOffers"] = [ $productOffer ];
  914.         $credentials null;
  915.         $videoLibrary $productPage->getLibrary();
  916.         if($videoLibrary){
  917.             $libraryRepository $this->em->getRepository(Library::class);
  918.             $credentials $libraryRepository->getVideoCredentials($videoLibrary);
  919.         }
  920.         $this->data["credentials"] = $credentials;
  921.         if($productPage->getType() == ProductPageEnum::TYPE_LAND_PAGE){
  922.             $pixelService $this->generalService->getService('Marketing\\PixelService');
  923.             $pixelService->sendConversion('AddToCart', (object)[
  924.                 "content_ids" => [ $productOffer->getId() ],
  925.                 "content_name" => $productOffer->getTitle(),
  926.                 "currency" => $productOffer->getCurrencyCode(),
  927.                 "value" => $productOffer->getPriceReal(),
  928.             ]);
  929.             if($this->user && $productOffer->getSaleOption() == ProductOfferEnum::FREE){
  930.                 $enrollmentService $this->generalService->getService(
  931.                     'EnrollmentService'
  932.                 );
  933.                 $enrollmentService->setOrigin(EnrollmentEnum::ORIGIN_FREE);
  934.                 $enrollmentService->enrollUserByProduct(
  935.                     $this->user,
  936.                     $productOffer->getProduct()
  937.                 );
  938.             }
  939.             return $this->renderEAD('product/landingpage/index.html.twig');
  940.         }
  941.         return $this->renderEAD("product/product-detail.html.twig");
  942.     }
  943.     /**
  944.      * @Route(
  945.      *      path          = "/{type}/{slug}/{offerHash}",
  946.      *      name          = "productDetailPlan",
  947.      *      methods       = {"GET"},
  948.      *      defaults      = { "offerHash": null },
  949.      *      requirements  = {"type"="plano|plan"}
  950.      * )
  951.      */
  952.     public function getProductPlanDetailPage(Request $request) {
  953.         $this->requestUtil->setRequest($request)->setData();
  954.         $utmsUrl http_build_query($this->requestUtil->getData());   
  955.         $this->data['utmsUrl'] = $utmsUrl;
  956.         $slug $request->get('slug');
  957.         $type $request->get('type');
  958.         $offerHash $request->get('offerHash');
  959.         $couponKey $request->get('coupon');
  960.         $pageId $request->get('page');
  961.         $productType ProductEnum::SUBSCRIPTION;
  962.         $productRepository $this->em->getRepository(Product::class);
  963.         $poRepository $this->em->getRepository(ProductOffer::class);
  964.         $poRepository $this->em->getRepository(ProductOffer::class);
  965.         $productOffer $poRepository->getProductBySlug(
  966.             $slug,
  967.             $productType,
  968.             $offerHash
  969.         );
  970.         if(!$productOffer){
  971.             $productOffer $poRepository->getProductBySlug(
  972.                 $slug,
  973.                 $productType
  974.             );
  975.             if(!$productOffer){
  976.                 return $this->redirectToRoute('notFound');
  977.             }
  978.             
  979.             $couponKey $offerHash;
  980.         }
  981.         if(
  982.             (
  983.                 $productOffer->getDefault() == ProductEnum::NO ||
  984.                 $productOffer->getSpotlight() == ProductEnum::NO
  985.             ) && empty($offerHash)
  986.         ){
  987.             $offerHash $productOffer->getOfferLink();
  988.         }
  989.         $product $productOffer->getProduct();
  990.         if($product->getType() != $productType){
  991.             return $this->redirectToRoute('notFound');
  992.         }
  993.         $productRelateds $product->getProductRelated();
  994.         $courseRepository $this->em->getRepository(Course::class);
  995.         $courses $courseRepository->getCoursesByProduct($product->getId());
  996.         $monthOffer $poRepository->getDefaultOrCustomByCycle(
  997.             $product,
  998.             ProductOfferEnum::CYCLE_MONTHLY,
  999.             $offerHash
  1000.         );
  1001.         $quarterlyOffer $poRepository->getDefaultOrCustomByCycle(
  1002.             $product,
  1003.             ProductOfferEnum::CYCLE_QUARTERLY,
  1004.             $offerHash
  1005.         );
  1006.         $semiannualOffer $poRepository->getDefaultOrCustomByCycle(
  1007.             $product,
  1008.             ProductOfferEnum::CYCLE_SEMIANNUAL,
  1009.             $offerHash
  1010.         );
  1011.         $yearlyOffer $poRepository->getDefaultOrCustomByCycle(
  1012.             $product,
  1013.             ProductOfferEnum::CYCLE_YEARLY,
  1014.             $offerHash
  1015.         );
  1016.         $biennialOffer $poRepository->getDefaultOrCustomByCycle(
  1017.             $product,
  1018.             ProductOfferEnum::CYCLE_BIENNIAL,
  1019.             $offerHash
  1020.         );
  1021.         $triennialOffer $poRepository->getDefaultOrCustomByCycle(
  1022.             $product,
  1023.             ProductOfferEnum::CYCLE_TRIENNIAL,
  1024.             $offerHash
  1025.         );
  1026.         $weeklyOffer $poRepository->getDefaultOrCustomByCycle(
  1027.             $product,
  1028.             ProductOfferEnum::CYCLE_WEEKLY,
  1029.             $offerHash
  1030.         );
  1031.         $biweeklyOffer $poRepository->getDefaultOrCustomByCycle(
  1032.             $product,
  1033.             ProductOfferEnum::CYCLE_BIWEEKLY,
  1034.             $offerHash
  1035.         );
  1036.         $productOffers array_filter([
  1037.             $monthOffer,
  1038.             $quarterlyOffer,
  1039.             $semiannualOffer,
  1040.             $yearlyOffer,
  1041.             $biennialOffer,
  1042.             $triennialOffer,
  1043.             $weeklyOffer,
  1044.             $biweeklyOffer,
  1045.         ]);
  1046.         $productOffer $poRepository->returnProductOfferOrProductNextPlan(
  1047.             $productOffer
  1048.             $productOffers
  1049.         );
  1050.         foreach ($productOffers as $key => $productOfferCycle) {
  1051.             if($productOfferCycle->getPlanCycle() == $productOffer->getPlanCycle()){
  1052.                 $productOffers[$key] = $productOffer;
  1053.             }
  1054.         }
  1055.         $productPage $productOffer->getProductPage();
  1056.         if(!empty($pageId) && $this->user){
  1057.             $permission $this->userPermissionUtil->getPermission("product""see");
  1058.             if(!$this->userPermissionUtil->isLow($permission)){
  1059.                 $productPage $this->em->getRepository(ProductPage::class)->find($pageId);
  1060.             }
  1061.         }
  1062.         if(!$productPage){
  1063.             return $this->redirectToRoute('notFound');
  1064.         }
  1065.         $externalPage $productPage->getExternalPage();
  1066.         $externalPageLink $productPage->getExternalPageLink();
  1067.         if($externalPage == ProductEnum::YES && !empty($externalPageLink)){
  1068.             return $this->redirect($externalPageLink301);
  1069.         }
  1070.         $this->data['productPage'] = $productPage;
  1071.         $this->data['formName'] = "formFastUserRegister";
  1072.         $this->data["productOffer"] = $productOffer;
  1073.         $this->data['certificate'] = CourseEnum::NO;
  1074.         $this->data['generateCertificate'] = CourseCertificateEnum::NO;
  1075.         $this->data['lessonModules'] = [];
  1076.         $this->data['couponKey'] = $couponKey;
  1077.         $this->data['couponKeyValid'] = false;
  1078.         $this->data['productCoupon'] = null;
  1079.         $productRepository $this->em->getRepository(Product::class);
  1080.         $productRepository->saveProductInCache($product);
  1081.         $pcRepository $this->em->getRepository(ProductCoupon::class);
  1082.         $this->data['productOfferCouponTotal'] = $pcRepository->countPublicCouponByProductOffer(
  1083.             $productOffer
  1084.         );
  1085.         if(!empty($couponKey)){
  1086.             foreach ($productOffers as $key => $productOfferCycle) {
  1087.                 $productCoupon $pcRepository->findValidProductCouponByProductOffer(
  1088.                     $couponKey,
  1089.                     $productOfferCycle
  1090.                 );
  1091.                 if($productCoupon){
  1092.                     $amount $productOfferCycle->getPriceReal();
  1093.                     $amount $pcRepository->applyDiscount($productCoupon$amount);
  1094.                     if($amount 0){
  1095.                         $this->data['couponKeyValid'] = true;
  1096.                         if($productOfferCycle->getPlanCycle() == $productOffer->getPlanCycle()){
  1097.                             $productOffer->setPriceRealCopy($amount);
  1098.                             $this->data['productCoupon'] = $productCoupon;
  1099.                         }
  1100.                         $productOfferCycle->setPriceRealCopy($amount);
  1101.                     }
  1102.                 }
  1103.             }
  1104.         }
  1105.         $psRepository $this->em->getRepository(ProductSuggestion::class);
  1106.         $productOfferSuggestions $psRepository->getProductSuggestionsByOfferOrigin(
  1107.             $productOffer,
  1108.             ProductSuggestionEnum::EXECUTE_IN_PRODUCT_PAGE
  1109.         );
  1110.         $productOfferSuggestionsAddCart $psRepository->getProductSuggestionsByOfferOrigin(
  1111.             $productOffer,
  1112.             ProductSuggestionEnum::EXECUTE_ON_ADD_CART
  1113.         );
  1114.         $this->data['productOfferSuggestions'] = $productOfferSuggestions;
  1115.         $this->data['emptyProductSuggestion'] = true;
  1116.         if(!empty($productOfferSuggestions) || !empty($productOfferSuggestionsAddCart)){
  1117.             $this->data['emptyProductSuggestion'] = false;
  1118.         }
  1119.         $numberUtil $this->generalService->getUtil('NumberUtil');
  1120.         $parcelInfo $numberUtil->getNumberMaxParcel(
  1121.             $productOffer->getPriceRealCopy(true),
  1122.             $poRepository->getInstallmentNumberMax($productOffer),
  1123.             $poRepository->getFreeInstallment($productOffer),
  1124.             $productOffer->getSaleOption(),
  1125.             $productOffer->getTypeCheckout(),
  1126.             false
  1127.         );
  1128.         $this->data["productOffers"] = $productOffers;
  1129.         $this->data['parcelInfo'] = $parcelInfo;
  1130.         $this->data['useCard'] = $poRepository->produtOfferAllowCard($productOffer);
  1131.         $this->data['useBill'] = $poRepository->produtOfferAllowBill($productOffer);
  1132.         $this->data['usePix'] = $poRepository->produtOfferAllowPix($productOffer);
  1133.         //ProductOffer Related
  1134.         $productOffersRelateds $poRepository->getProductRelatedOffers(
  1135.             $product
  1136.         );
  1137.         
  1138.         //Permission to view draft page
  1139.         if($product->getStatus() == ProductEnum::DRAFT){
  1140.             $this->checkUserSession($request);
  1141.             $permission $this->userPermissionUtil->getPermission("product""see");
  1142.             if($this->userPermissionUtil->isLow($permission)){
  1143.                 return $this->redirectToRoute('notFound');
  1144.             }
  1145.             $isInTeam $this->em->getRepository(ProductTeam::class)->userExistInProductTeam(
  1146.                 $product,
  1147.                 $this->user
  1148.             );
  1149.             if(!$isInTeam && $this->userPermissionUtil->isMiddle($permission)){
  1150.                 return $this->redirectToRoute('notFound');
  1151.             }
  1152.         }
  1153.         $this->data['product'] = $product;
  1154.         //FAQ
  1155.         $this->data['faqs'] = $this->em->getRepository(Faq::class)->getFaqForProductDetail(
  1156.             $product
  1157.         );
  1158.         //Course Team
  1159.         $teachers $this->em->getRepository(User::class)->getUserTeachersFromProduct(
  1160.             $product
  1161.         );
  1162.         //Product total
  1163.         $this->data['courseTotal'] = $courseRepository->getPublishedCourseNumberByProduct(
  1164.             $product->getId()
  1165.         );
  1166.         $this->data['teacherSection'] = (object)[
  1167.             "teachers" => $teachers,
  1168.             "isCenterTitle" => false,
  1169.             "title" => $this->configuration->getLanguage('instructors''product'),
  1170.             "showSubtitle" => false,
  1171.             "subtitle" => '',
  1172.             "showBtnToAll" => false,
  1173.         ];
  1174.         $this->data['productOffersRelatedsSection'] = (object)[
  1175.             "title" => $this->configuration->getLanguage('related_courses''product'),
  1176.             "subtitle" => $this->configuration->getLanguage('extend_your_knowledge''product'),
  1177.             "name" => "product-related",
  1178.             "items" => $productOffersRelateds,
  1179.             "background" => true,
  1180.             "expand" => false,
  1181.             "slider" => true,
  1182.         ];
  1183.         $this->data['planCoursesSection'] = (object)[
  1184.             "title" => $this->configuration->getLanguage('courses_included_plan''product'),
  1185.             "subtitle" => "",
  1186.             "name" => "product-plan-course",
  1187.             "items" => $courses,
  1188.             "background" => true,
  1189.             "expand" => false,
  1190.             "slider" => false,
  1191.             "isCourse" => true,
  1192.             "itemsTotal" => $this->data['courseTotal']
  1193.         ];
  1194.         $this->data['productOffersSubscriptionSection'] = (object)[
  1195.             "title" => $this->configuration->getLanguage('you_can_expand''product'),
  1196.             "subtitle" => $this->configuration->getLanguage('sign_up_for_a_plan''product'),
  1197.             "name" => "product-subscription-course",
  1198.             "items" => [],
  1199.             "background" => true,
  1200.             "expand" => false,
  1201.             "slider" => false,
  1202.             "isCourse" => true,
  1203.             "itemsTotal" => $this->data['courseTotal']
  1204.         ];
  1205.         $courseTestimonialRepository $this->em->getRepository(CourseTestimonial::class);
  1206.         //Course Stars
  1207.         $this->data['scoreProduct'] = $courseTestimonialRepository->getScoreByProduct(
  1208.             $product
  1209.         );
  1210.         $this->data['scoreProduct']->splitScore = [
  1211.             $this->data['scoreProduct']->fiveStar,
  1212.             $this->data['scoreProduct']->fourStar,
  1213.             $this->data['scoreProduct']->threeStar,
  1214.             $this->data['scoreProduct']->twoStar,
  1215.             $this->data['scoreProduct']->oneStar ,
  1216.         ];
  1217.         //Course Testimonials
  1218.         $this->data['courseTestimonials'] = $courseTestimonialRepository->getTestimonialApprovedRandom(
  1219.             $this->testimonialLimit,
  1220.             $product
  1221.         );
  1222.         foreach ($this->data['courseTestimonials'] as $key => $value) {
  1223.             
  1224.             $value['testimonial'] = StringUtil::encodeStringStatic($value['testimonial']);
  1225.             $value['userName'] = StringUtil::encodeStringStatic($value['userName']);
  1226.             $this->data['courseTestimonials'][$key] = $value;
  1227.         }
  1228.         
  1229.         //Lesson Module Total
  1230.         $lessonModuleRepository $this->em->getRepository(LessonModule::class);
  1231.         $this->data['lessonModuleTotal'] = $lessonModuleRepository->getLessonModuleNumberByProduct(
  1232.             $product
  1233.         );
  1234.         //Lesson Total
  1235.         $lessonRepository $this->em->getRepository(Lesson::class);
  1236.         $this->data['lessonTotal'] = $lessonRepository->getLessonNumberByProduct(
  1237.             $product
  1238.         );
  1239.         $dateLastUpdate null;
  1240.         $auxCourses = [];
  1241.         foreach ($courses as $key => $course) {
  1242.             if($course->getStatus() == CourseEnum::PUBLISHED){
  1243.                 $lastUpdate $course->getDateUpdate();
  1244.                 if(empty($dateLastUpdate) || $lastUpdate $dateLastUpdate){
  1245.                     $dateLastUpdate $lastUpdate;
  1246.                 }
  1247.                 if($course->getCertificate() == CourseEnum::YES){
  1248.                     $this->data['certificate'] = CourseEnum::YES;
  1249.                 }
  1250.                 $auxCourses[] = $course;
  1251.             }
  1252.         }
  1253.         $this->data['dateLastUpdate'] = $dateLastUpdate;
  1254.         
  1255.         //Courses
  1256.         $this->data['courses'] = $auxCourses;
  1257.         $this->data['accessPeriod'] = 0;
  1258.         $this->data['lifetimePeriod'] = CourseEnum::NO;
  1259.         $this->data['support'] = CourseEnum::NO;
  1260.         $this->data['supportPeriod'] = 0;
  1261.         $this->data['lifetimeSupport'] = CourseEnum::NO;
  1262.         $this->data['enrollmentTotal'] = 0;
  1263.         //User Subscription total
  1264.         $userSubscriptionRepository $this->em->getRepository(UserSubscription::class);
  1265.         $this->data['userSubscriptionTotal'] = $userSubscriptionRepository->getUserSubscriptionActiveNumberByProduct(
  1266.             $product
  1267.         );
  1268.         $this->data['keyCaptcha'] = $this->createCaptchaKey($request);
  1269.         //Product time total
  1270.         $this->data['timeTotal'] = $courseRepository->getAllCourseTimeByProduct($product);
  1271.         //Sale number limit
  1272.         $poRepository $this->em->getRepository(ProductOffer::class);
  1273.         $this->data['saleLimitRemaining'] = $poRepository->getProductOfferSaleLimitRemaining($productOffer);
  1274.         //Product files total
  1275.         $lessonXLibraryRepository $this->em->getRepository(LessonXLibrary::class);
  1276.         $this->data['fileTotal'] = $lessonXLibraryRepository->getLessonXLibraryFilesByProduct(
  1277.             $product
  1278.         );
  1279.         if($this->user){
  1280.             $marketingService $this->generalService->getService(
  1281.                 'Marketing\\MarketingService'
  1282.             );
  1283.             $marketingService->setTag(TagsMarketingEnum::TAG_VISITED_PAGE);
  1284.             $marketingService->setTextComplement($product->getTitle());
  1285.             $marketingService->setUser($this->user);
  1286.             $marketingService->setProductOffer($productOffer);
  1287.             $marketingService->setOpportunity(ProductOpportunityEnum::TAG_VISITED_PAGE);
  1288.             $marketingService->send();
  1289.         }
  1290.         $pagarMeTransaction $this->generalService->getService(
  1291.             'PagarMe\\PagarMeTransaction'
  1292.         );
  1293.         $paymentConfig $this->configuration->getPaymentConfig();
  1294.         $installmentsOptions $pagarMeTransaction->calculateInstallments([
  1295.             'amount' => $productOffer->getPriceRealCopy(true),
  1296.             'free_installments' => $poRepository->getFreeInstallment($productOffer),
  1297.             'max_installments' => $parcelInfo->maxInstallments,
  1298.             'interest_rate' => $paymentConfig->installmentInterest
  1299.         ]);
  1300.         $this->data['installmentsOptions'] = (array)$installmentsOptions;
  1301.         $userCards null;
  1302.         $userCheckoutInfos null;
  1303.         if($this->user){
  1304.             $userCardRepository $this->em->getRepository(UserCard::class);
  1305.             $userCards $userCardRepository->getValidUserCard();
  1306.             $userCheckoutInfoRepository $this->em->getRepository(UserCheckoutInfo::class);
  1307.             $userCheckoutInfos $userCheckoutInfoRepository->findBy([
  1308.                 "user" => $this->user->getId(),
  1309.                 "deleted" => UserCheckoutInfoEnum::ITEM_NO_DELETED
  1310.             ], [ "default" => "DESC" ]);
  1311.         }
  1312.         $this->data["isOnSale"] = $poRepository->checkProductOfferIsOnSale($productOffer);
  1313.         $this->data["userCards"] = $userCards;
  1314.         $this->data["userCheckoutInfos"] = $userCheckoutInfos;
  1315.         $credentials null;
  1316.         $videoLibrary $productPage->getLibrary();
  1317.         if($videoLibrary){
  1318.             $libraryRepository $this->em->getRepository(Library::class);
  1319.             $credentials $libraryRepository->getVideoCredentials($videoLibrary);
  1320.         }
  1321.         $this->data["credentials"] = $credentials;
  1322.         if($productPage->getType() == ProductPageEnum::TYPE_LAND_PAGE){
  1323.             $pixelService $this->generalService->getService('Marketing\\PixelService');
  1324.             $pixelService->sendConversion('AddToCart', (object)[
  1325.                 "content_ids" => [ $productOffer->getId() ],
  1326.                 "content_name" => $productOffer->getTitle(),
  1327.                 "currency" => $productOffer->getCurrencyCode(),
  1328.                 "value" => $productOffer->getPriceReal(),
  1329.             ]);
  1330.             return $this->renderEAD('product/landingpage/index.html.twig');
  1331.         }
  1332.         return $this->renderEAD("product/product-detail.html.twig");
  1333.     }
  1334.     /**
  1335.      * @Route(
  1336.      *      path          = "/{type}/{slug}/{offerHash}",
  1337.      *      name          = "productDetailCombo",
  1338.      *      methods       = {"GET"},
  1339.      *      defaults      = { "offerHash": null },
  1340.      *      requirements  = {"type"="combo"}
  1341.      * )
  1342.      */
  1343.     public function getProductComboDetailPage(Request $request) {
  1344.         $this->requestUtil->setRequest($request)->setData();
  1345.         $utmsUrl http_build_query($this->requestUtil->getData());   
  1346.         $this->data['utmsUrl'] = $utmsUrl;
  1347.         
  1348.         $slug $request->get('slug');
  1349.         $type $request->get('type');
  1350.         $offerHash $request->get('offerHash');
  1351.         $couponKey $request->get('coupon');
  1352.         $pageId $request->get('page');
  1353.         $productType ProductEnum::COMBO;
  1354.         $poRepository $this->em->getRepository(ProductOffer::class);
  1355.         $productOffer $poRepository->getProductBySlug(
  1356.             $slug,
  1357.             $productType,
  1358.             $offerHash
  1359.         );
  1360.         if(!$productOffer){
  1361.             $productOffer $poRepository->getProductBySlug(
  1362.                 $slug,
  1363.                 $productType
  1364.             );
  1365.             $couponKey $offerHash;
  1366.             
  1367.             if(!$productOffer){
  1368.                 return $this->redirectToRoute('notFound');
  1369.             }
  1370.         }
  1371.         $product $productOffer->getProduct();
  1372.         if($product->getType() != $productType){
  1373.             return $this->redirectToRoute('notFound');
  1374.         }
  1375.         $productOffer $poRepository->returnProductOfferOrProductNextClean($productOffer);
  1376.         
  1377.         $productPage $productOffer->getProductPage();
  1378.         if(!empty($pageId) && $this->user){
  1379.             $permission $this->userPermissionUtil->getPermission("product""see");
  1380.             if(!$this->userPermissionUtil->isLow($permission)){
  1381.                 $productPage $this->em->getRepository(ProductPage::class)->find($pageId);
  1382.             }
  1383.         }
  1384.         if(!$productPage){
  1385.             return $this->redirectToRoute('notFound');
  1386.         }
  1387.         
  1388.         $externalPage $productPage->getExternalPage();
  1389.         $externalPageLink $productPage->getExternalPageLink();
  1390.         if($externalPage == ProductEnum::YES && !empty($externalPageLink)){
  1391.             return $this->redirect($externalPageLink301);
  1392.         }
  1393.         $this->data['productPage'] = $productPage;
  1394.         $productRelateds $product->getProductRelated();
  1395.         $courseRepository $this->em->getRepository(Course::class);
  1396.         $courses $courseRepository->getCoursesByProduct($product->getId());
  1397.         $this->data['couponKey'] = $couponKey;
  1398.         $this->data['couponKeyValid'] = false;
  1399.         $this->data['productCoupon'] = null;
  1400.         $productRepository $this->em->getRepository(Product::class);
  1401.         $productRepository->saveProductInCache($product);
  1402.         
  1403.         $pcRepository $this->em->getRepository(ProductCoupon::class);
  1404.         $this->data['productOfferCouponTotal'] = $pcRepository->countPublicCouponByProductOffer(
  1405.             $productOffer
  1406.         );
  1407.         $this->data['certificate'] = CourseEnum::NO;
  1408.         $this->data['generateCertificate'] = CourseCertificateEnum::NO;
  1409.         
  1410.         if(!empty($couponKey)){
  1411.             $productCoupon $pcRepository->findValidProductCouponByProductOffer(
  1412.                 $couponKey,
  1413.                 $productOffer
  1414.             );
  1415.             if($productCoupon){
  1416.                 $amount $productOffer->getPriceReal();
  1417.                 $amount $pcRepository->applyDiscount($productCoupon$amount);
  1418.                 if($amount 0){
  1419.                     $this->data['couponKeyValid'] = true;
  1420.                     $this->data['productCoupon'] = $productCoupon;
  1421.                     $productOffer->setPriceRealCopy($amount);
  1422.                 }else{
  1423.                     if($this->user){
  1424.                         $productCoupon->setUsageNumber($productCoupon->getUsageNumber() + 1);
  1425.                         $this->em->flush();
  1426.                         $enrollmentService $this->generalService->getService(
  1427.                             'EnrollmentService'
  1428.                         );
  1429.     
  1430.                         $enrollmentService->setOrigin(EnrollmentEnum::ORIGIN_COUPOM);
  1431.                         $enrollmentService->setCouponKey($couponKey);
  1432.                         $enrollmentService->enrollUserByProduct(
  1433.                             $this->user,
  1434.                             $productOffer->getProduct()
  1435.                         );
  1436.                     }else{
  1437.                         $params = [
  1438.                             "poID" => $productOffer->getId(),
  1439.                             "pcID" => $productCoupon->getId(),
  1440.                         ];
  1441.                         return $this->redirectToRoute('cartAdd'$params);
  1442.                     }
  1443.                 }
  1444.             }
  1445.         }
  1446.         $numberUtil $this->generalService->getUtil('NumberUtil');
  1447.         $parcelInfo $numberUtil->getNumberMaxParcel(
  1448.             $productOffer->getPriceRealCopy(true),
  1449.             $poRepository->getInstallmentNumberMax($productOffer),
  1450.             $poRepository->getFreeInstallment($productOffer),
  1451.             $productOffer->getSaleOption(),
  1452.             $productOffer->getTypeCheckout(),
  1453.             false
  1454.         );
  1455.         $this->data['parcelInfo'] = $parcelInfo;
  1456.         $this->data['useCard'] = $poRepository->produtOfferAllowCard($productOffer);
  1457.         $this->data['useBill'] = $poRepository->produtOfferAllowBill($productOffer);
  1458.         $this->data['usePix'] = $poRepository->produtOfferAllowPix($productOffer);
  1459.         
  1460.         //ProductOffer Related
  1461.         $productOffersRelateds $poRepository->getProductRelatedOffers(
  1462.             $product
  1463.         );
  1464.         
  1465.         //Permission to view draft page
  1466.         if(
  1467.             $productOffer->getStatus() == ProductOfferEnum::DRAFT || 
  1468.             $product->getStatus() == ProductEnum::DRAFT
  1469.         ){
  1470.             $this->checkUserSession($request);
  1471.             $permission $this->userPermissionUtil->getPermission("product""see");
  1472.             if($this->userPermissionUtil->isLow($permission)){
  1473.                 return $this->redirectToRoute('notFound');
  1474.             }
  1475.             $isInTeam $this->em->getRepository(ProductTeam::class)->userExistInProductTeam(
  1476.                 $product,
  1477.                 $this->user
  1478.             );
  1479.             if(!$isInTeam && $this->userPermissionUtil->isMiddle($permission)){
  1480.                 return $this->redirectToRoute('notFound');
  1481.             }
  1482.         }
  1483.         $this->data['productOffer'] = $productOffer;
  1484.         $this->data['product'] = $product;
  1485.         $psRepository $this->em->getRepository(ProductSuggestion::class);
  1486.         $productOfferSuggestions $psRepository->getProductSuggestionsByOfferOrigin(
  1487.             $productOffer,
  1488.             ProductSuggestionEnum::EXECUTE_IN_PRODUCT_PAGE
  1489.         );
  1490.         $productOfferSuggestionsAddCart $psRepository->getProductSuggestionsByOfferOrigin(
  1491.             $productOffer,
  1492.             ProductSuggestionEnum::EXECUTE_ON_ADD_CART
  1493.         );
  1494.         $this->data['productOfferSuggestions'] = $productOfferSuggestions;
  1495.         $this->data['emptyProductSuggestion'] = true;
  1496.         if(!empty($productOfferSuggestions) || !empty($productOfferSuggestionsAddCart)){
  1497.             $this->data['emptyProductSuggestion'] = false;
  1498.         }
  1499.         
  1500.         //FAQ
  1501.         $this->data['faqs'] = $this->em->getRepository(Faq::class)->getFaqForProductDetail(
  1502.             $product
  1503.         );
  1504.         //Course Team
  1505.         $teachers $this->em->getRepository(User::class)->getUserTeachersFromProduct(
  1506.             $product
  1507.         );
  1508.         //Product total
  1509.         $this->data['courseTotal'] = $courseRepository->getPublishedCourseNumberByProduct(
  1510.             $product->getId()
  1511.         );
  1512.         $this->data['formName'] = "formFastUserRegister";
  1513.         $this->data['teacherSection'] = (object)[
  1514.             "teachers" => $teachers,
  1515.             "isCenterTitle" => false,
  1516.             "title" => $this->configuration->getLanguage('instructors''product'),
  1517.             "showSubtitle" => false,
  1518.             "subtitle" => '',
  1519.             "showBtnToAll" => false,
  1520.         ];
  1521.         $this->data['productOffersRelatedsSection'] = (object)[
  1522.             "title" => $this->configuration->getLanguage('related_courses''product'),
  1523.             "subtitle" => $this->configuration->getLanguage('extend_your_knowledge''product'),
  1524.             "name" => "product-related",
  1525.             "items" => $productOffersRelateds,
  1526.             "background" => true,
  1527.             "expand" => false,
  1528.             "slider" => true,
  1529.         ];
  1530.         $this->data['planCoursesSection'] = (object)[
  1531.             "title" => $this->configuration->getLanguage('courses_included_combo''product'),
  1532.             "subtitle" => "",
  1533.             "name" => "product-plan-course",
  1534.             "items" => $courses,
  1535.             "background" => true,
  1536.             "expand" => false,
  1537.             "slider" => false,
  1538.             "isCourse" => true,
  1539.             "itemsTotal" => $this->data['courseTotal'],
  1540.         ];
  1541.         $this->data['productOffersSubscriptionSection'] = (object)[
  1542.             "title" => $this->configuration->getLanguage('you_can_expand''product'),
  1543.             "subtitle" => $this->configuration->getLanguage('sign_up_for_a_plan''product'),
  1544.             "name" => "product-subscription-course",
  1545.             "items" => [],
  1546.             "background" => true,
  1547.             "expand" => false,
  1548.             "slider" => false,
  1549.             "isCourse" => true,
  1550.             "itemsTotal" => $this->data['courseTotal']
  1551.         ];
  1552.         $courseTestimonialRepository $this->em->getRepository(CourseTestimonial::class);
  1553.         //Course Stars
  1554.         $this->data['scoreProduct'] = $courseTestimonialRepository->getScoreByProduct(
  1555.             $product
  1556.         );
  1557.         $this->data['scoreProduct']->splitScore = [
  1558.             $this->data['scoreProduct']->fiveStar,
  1559.             $this->data['scoreProduct']->fourStar,
  1560.             $this->data['scoreProduct']->threeStar,
  1561.             $this->data['scoreProduct']->twoStar,
  1562.             $this->data['scoreProduct']->oneStar ,
  1563.         ];
  1564.         //Course Testimonials
  1565.         $this->data['courseTestimonials'] = $courseTestimonialRepository->getTestimonialApprovedRandom(
  1566.             $this->testimonialLimit,
  1567.             $product
  1568.         );
  1569.         foreach ($this->data['courseTestimonials'] as $key => $value) {
  1570.             
  1571.             $value['testimonial'] = StringUtil::encodeStringStatic($value['testimonial']);
  1572.             $value['userName'] = StringUtil::encodeStringStatic($value['userName']);
  1573.             $this->data['courseTestimonials'][$key] = $value;
  1574.         }
  1575.         
  1576.         //Lesson Module Total
  1577.         $lessonModuleRepository $this->em->getRepository(LessonModule::class);
  1578.         $this->data['lessonModuleTotal'] = $lessonModuleRepository->getLessonModuleNumberByProduct(
  1579.             $product
  1580.         );
  1581.         //Lesson Total
  1582.         $lessonRepository $this->em->getRepository(Lesson::class);
  1583.         $this->data['lessonTotal'] = $lessonRepository->getLessonNumberByProduct(
  1584.             $product
  1585.         );
  1586.         $dateLastUpdate null;
  1587.         $auxCourses = [];
  1588.         foreach ($courses as $key => $course) {
  1589.             if($course->getStatus() == CourseEnum::PUBLISHED){
  1590.                 $lastUpdate $course->getDateUpdate();
  1591.                 if(empty($dateLastUpdate) || $lastUpdate $dateLastUpdate){
  1592.                     $dateLastUpdate $lastUpdate;
  1593.                 }
  1594.                 if($course->getCertificate() == CourseEnum::YES){
  1595.                     $this->data['certificate'] = CourseEnum::YES;
  1596.                 }
  1597.                 $auxCourses[] = $course;
  1598.             }
  1599.         }
  1600.         $this->data['dateLastUpdate'] = $dateLastUpdate;
  1601.         
  1602.         //Courses
  1603.         $this->data['courses'] = $auxCourses;
  1604.         $this->data['enrollmentTotal'] = 0;
  1605.         $this->data['userSubscriptionTotal'] = 0;
  1606.         $this->data['accessPeriod'] = 0;
  1607.         $this->data['lifetimePeriod'] = CourseEnum::NO;
  1608.         $this->data['support'] = CourseEnum::NO;
  1609.         $this->data['supportPeriod'] = 0;
  1610.         $this->data['lifetimeSupport'] = CourseEnum::NO;
  1611.         $this->data['lessonModules'] = [];
  1612.         //Sale number limit
  1613.         $poRepository $this->em->getRepository(ProductOffer::class);
  1614.         $this->data['saleLimitRemaining'] = $poRepository->getProductOfferSaleLimitRemaining($productOffer);
  1615.         //Product time total
  1616.         $this->data['timeTotal'] = $courseRepository->getAllCourseTimeByProduct($product);
  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->getValidUserCard();
  1651.             $userCheckoutInfoRepository $this->em->getRepository(UserCheckoutInfo::class);
  1652.             $userCheckoutInfos $userCheckoutInfoRepository->findBy([
  1653.                 "user" => $this->user->getId(),
  1654.                 "deleted" => UserCheckoutInfoEnum::ITEM_NO_DELETED
  1655.             ], [ "default" => "DESC" ]);
  1656.         }
  1657.         $this->data["isOnSale"] = $poRepository->checkProductOfferIsOnSale($productOffer);
  1658.         $this->data["userCards"] = $userCards;
  1659.         $this->data["userCheckoutInfos"] = $userCheckoutInfos;
  1660.         $credentials null;
  1661.         $videoLibrary $productPage->getLibrary();
  1662.         if($videoLibrary){
  1663.             $libraryRepository $this->em->getRepository(Library::class);
  1664.             $credentials $libraryRepository->getVideoCredentials($videoLibrary);
  1665.         }
  1666.         $this->data["credentials"] = $credentials;
  1667.         if($productPage->getType() == ProductPageEnum::TYPE_LAND_PAGE){
  1668.             if($this->user && $productOffer->getSaleOption() == ProductOfferEnum::FREE){
  1669.                 $enrollmentService $this->generalService->getService(
  1670.                     'EnrollmentService'
  1671.                 );
  1672.                 $enrollmentService->setOrigin(EnrollmentEnum::ORIGIN_FREE);
  1673.                 $enrollmentService->enrollUserByProduct(
  1674.                     $this->user,
  1675.                     $productOffer->getProduct()
  1676.                 );
  1677.             }
  1678.             $pixelService $this->generalService->getService('Marketing\\PixelService');
  1679.             $pixelService->sendConversion('AddToCart', (object)[
  1680.                 "content_ids" => [ $productOffer->getId() ],
  1681.                 "content_name" => $productOffer->getTitle(),
  1682.                 "currency" => $productOffer->getCurrencyCode(),
  1683.                 "value" => $productOffer->getPriceReal(),
  1684.             ]);
  1685.             
  1686.             return $this->renderEAD('product/landingpage/index.html.twig');
  1687.         }
  1688.         return $this->renderEAD("product/product-detail.html.twig");
  1689.     }
  1690. }