src/AtechNet/CoreBundle/Controller/ProductController.php line 9261

Open in your IDE?
  1. <?php
  2. namespace App\AtechNet\CoreBundle\Controller;
  3. use App\AtechNet\CoreBundle\Entity\Attribute;
  4. use App\AtechNet\CoreBundle\Entity\AttributeOption;
  5. use App\AtechNet\CoreBundle\Entity\CategoryPage;
  6. use App\AtechNet\CoreBundle\Entity\Coupon;
  7. use App\AtechNet\CoreBundle\Entity\Customer;
  8. use App\AtechNet\CoreBundle\Entity\CustomerNotification;
  9. use App\AtechNet\CoreBundle\Entity\Domain;
  10. use App\AtechNet\CoreBundle\Entity\DomainShippingType;
  11. use App\AtechNet\CoreBundle\Entity\ErrorCode;
  12. use App\AtechNet\CoreBundle\Entity\Language;
  13. use App\AtechNet\CoreBundle\Entity\PageMeta;
  14. use App\AtechNet\CoreBundle\Entity\Product;
  15. use App\AtechNet\CoreBundle\Entity\ProductAttribute;
  16. use App\AtechNet\CoreBundle\Entity\ProductMeta;
  17. use App\AtechNet\CoreBundle\Entity\ProductType;
  18. use App\AtechNet\CoreBundle\Entity\Review;
  19. use App\AtechNet\CoreBundle\Entity\ReviewSurveyMedia;
  20. use App\AtechNet\CoreBundle\Entity\SeoUrl;
  21. use App\AtechNet\CoreBundle\Entity\StockItem;
  22. use App\AtechNet\CoreBundle\Entity\SurveyMedia;
  23. use App\AtechNet\CoreBundle\Entity\User;
  24. use App\AtechNet\CoreBundle\Entity\Vendor;
  25. use App\AtechNet\CoreBundle\Form\ReviewType;
  26. use App\AtechNet\CoreBundle\Helper\Collections;
  27. use App\AtechNet\CoreBundle\Helper\DeliveryUtil as DeliveryDate;
  28. use App\AtechNet\CoreBundle\Helper\Furbify\CartHelper;
  29. use App\AtechNet\CoreBundle\Helper\Furbify\Heureka;
  30. use App\AtechNet\CoreBundle\Helper\Furbify\Image;
  31. use App\AtechNet\CoreBundle\Helper\Furbify\MultiStore;
  32. use App\AtechNet\CoreBundle\Helper\Furbify\ProductHelper;
  33. use App\AtechNet\CoreBundle\Helper\Furbify\SearchHelper;
  34. use App\AtechNet\CoreBundle\Helper\Furbify\TextHelper;
  35. use App\AtechNet\CoreBundle\Helper\Packeta;
  36. use App\AtechNet\CoreBundle\Sevices\ProductService;
  37. use App\AtechNet\CoreBundle\Translation\DatabaseTranslator;
  38. use Mpdf\Config\ConfigVariables;
  39. use Mpdf\Config\FontVariables;
  40. use Mpdf\Mpdf;
  41. use Psr\Cache\CacheItemPoolInterface;
  42. use Psr\SimpleCache\InvalidArgumentException;
  43. use Symfony\Bridge\Twig\Mime\TemplatedEmail;
  44. use Symfony\Component\HttpFoundation\JsonResponse;
  45. use Symfony\Component\HttpFoundation\RedirectResponse;
  46. use Symfony\Component\HttpFoundation\Request;
  47. use Symfony\Component\HttpFoundation\Response;
  48. use Symfony\Component\Routing\Annotation\Route;
  49. use Symfony\Component\Stopwatch\Stopwatch;
  50. class ProductController extends AbstractController
  51. {
  52.     public const READY_BOX_PRODUCT_TYPES = [
  53.         52,     // Notebook
  54.         60,     // PC
  55.         107,    // PC SET
  56.         116,    // ALL IN ONE
  57.         77,     // SERVER
  58.     ];
  59.     private const REGENERATE_CACHE_TOKEN = '4d23c8c0629bf93f2a68e999df58283a';
  60.     private function parseSizeToGb(?string $title): ?int
  61.     {
  62.         if (is_null($title)) {
  63.             return null;
  64.         }
  65.         if (!preg_match('/(\d+(?:\.\d+)?)\s*(TB|GB)/i', $title, $m)) {
  66.             return null;
  67.         }
  68.         $value = (float) $m[1];
  69.         $unit  = strtoupper($m[2]);
  70.         return $unit === 'TB'
  71.             ? (int) ($value * 1024)
  72.             : (int) $value;
  73.     }
  74.     /**
  75.      * @Route("/product/{productId}", name="product_show", defaults={"_locale":""})
  76.      * @Route("/{_locale<%supported_locales%>?}/product/{productId}", name="product_show_locale", defaults={"_locale":""})
  77.      * @param int $productId
  78.      * @param Request $request
  79.      * @return Response
  80.      * @throws \Exception
  81.      */
  82.     public function showAction($productId, Request $request): Response
  83.     {
  84.         // get rid of bots trying to access old search page
  85.         if ($productId == 'search' || !is_numeric($productId)) {
  86.             return $this->redirectToRoute('not_found');
  87.         }
  88.         $multiStore = $this->getMultiStoreHelper($request);
  89.         $entityManager = $this->getEntityManager();
  90.         $productHelper = $this->getProductHelper($request);
  91.         $domain = $multiStore->getDomain();
  92.         $domainId = $domain->getId();
  93.         $cache = $this->cache;
  94.         $productCacheKey = ProductHelper::getProductCacheKey($domainId, $request->getLocale(), $productId);
  95.         $productCacheItem = $cache->getItem($productCacheKey);
  96.         $productCacheTimeKey = ProductHelper::getProductCacheKey($domainId, $request->getLocale(), $productId) . '.time';
  97.         $productCacheTimeItem = $cache->getItem($productCacheTimeKey);
  98.         if ($productCacheItem->isHit()) {
  99.             // Product Cache Data
  100.             $pcd = $productCacheItem->get();
  101.             // Product Live Data
  102.             $pld = $entityManager->createQuery("SELECT p.id, p.available, pm.orderable, pm.active, pm.discounted, c.id as CouponId, c.showBadgeOnWebsite as showCouponBadgeOnWebsite
  103.                     FROM AtechNetCoreBundle:Product p
  104.                     LEFT JOIN AtechNetCoreBundle:ProductMeta pm WITH pm.product = p AND pm.domain = :domain
  105.                     LEFT JOIN AtechNetCoreBundle:Coupon c WITH :productId MEMBER OF c.products AND c.domain = :domain AND c.enabled = true AND c.validFrom <= :now AND (c.validTo IS NULL OR c.validTo >= :now)
  106.                     WHERE p.id = :productId")
  107.                 ->setParameters([
  108.                     'domain' => $domain,
  109.                     'productId' => $productId,
  110.                     'now' => new \DateTime('now'),
  111.                 ])
  112.                 ->getResult();
  113.             if (count($pld) == 0) {
  114.                 return $this->redirectToRoute('not_found');
  115.             }
  116.             $pld = $pld[0];
  117.             $valid = (int)$pcd['available'] == (int)$pld['available']
  118.                 && (int)$pcd['orderable'] == (int)$pld['orderable']
  119.                 && (int)$pcd['active'] == (int)$pld['active']
  120.                 && (int)$pcd['isDiscounted'] == (int)$pld['discounted'];
  121.             if (isset($pcd['coupon']) && (($pcd['coupon']['id'] != $pld['CouponId']) || ($pcd['coupon']['showCouponBadgeOnWebsite'] != $pld['showCouponBadgeOnWebsite']))) {
  122.                 $valid = false;
  123.             } elseif (!isset($pcd['coupon']) && $pld['CouponId'] != null) {
  124.                 $valid = false;
  125.             }
  126.             $product = $entityManager->getRepository(Product::class)->find($productId);
  127.             $productMetaForLanguage = $product->getProductModel()?->getMetaByLanguage($domain->getLanguage()->getCode());
  128.             if (!is_null($productMetaForLanguage?->getText())) {
  129.                 if (!isset($pcd['productModelDescription'])) {
  130.                     $valid = false;
  131.                 } else {
  132.                     if ($productMetaForLanguage->getText() != $pcd['productModelDescription']) {
  133.                         $valid = false;
  134.                     }
  135.                 }
  136.             } else {
  137.                 if (isset($pcd['productModelDescription'])) {
  138.                     $valid = false;
  139.                 }
  140.             }
  141.             if ($valid) {
  142.                 $data = $pcd;
  143.             } else {
  144.                 $data = $this->getProductViewData($productId, $request, $domain, $entityManager, $multiStore);
  145.                 $productCacheItem->set($data);
  146.                 $productCacheItem->expiresAfter(self::CACHE_LIFETIME_7_DAYS);
  147.                 $cache->save($productCacheItem);
  148.                 $productCacheTimeItem->set((new \DateTime('now'))->getTimestamp());
  149.                 $productCacheTimeItem->expiresAfter(self::CACHE_LIFETIME_7_DAYS);
  150.                 $cache->save($productCacheTimeItem);
  151.             }
  152.         } else {
  153.             $data = $this->getProductViewData($productId, $request, $domain, $entityManager, $multiStore);
  154.             $productCacheItem->set($data);
  155.             $productCacheItem->expiresAfter(self::CACHE_LIFETIME_7_DAYS);
  156.             $cache->save($productCacheItem);
  157.             $productCacheTimeItem->set((new \DateTime('now'))->getTimestamp());
  158.             $productCacheTimeItem->expiresAfter(self::CACHE_LIFETIME_7_DAYS);
  159.             $cache->save($productCacheTimeItem);
  160.         }
  161.         //For EU doamins add all keyboard reprints
  162.         if (in_array($domainId, [Domain::DOMAIN_ID_WS_EU, Domain::DOMAIN_ID_RT_EU])) {
  163.             //Check if product already has a reprint option
  164.             $existsKeyboardReprint = array_filter($data['secondaryOptions'], function ($item) {
  165.                 return isset($item['id']) && $item['id'] == Attribute::ATTRIBUTE_ID_ACCESSORY_KEYBOARD_REPRINT;
  166.             });
  167.             if (count($existsKeyboardReprint) > 0) {
  168.                 $key = array_key_first($existsKeyboardReprint);
  169.                 //Get all languages
  170.                 $allKeyboardLanguages = $entityManager->getRepository(AttributeOption::class)
  171.                     ->createQueryBuilder('ao')
  172.                     ->where('ao.attribute = :attribute')
  173.                     ->andWhere('ao.title NOT LIKE :excludedWord')
  174.                     ->andWhere('ao.title != :excludedExactWord')
  175.                     ->andWhere('ao.archived = 0')
  176.                     ->setParameter('attribute', Attribute::ATTRIBUTE_ID_ACCESSORY_KEYBOARD_REPRINT)
  177.                     ->setParameter('excludedWord', '%backlit%')
  178.                     ->setParameter('excludedExactWord', "Don't need")
  179.                     ->getQuery()->getResult();
  180.                 /** @var AttributeOption $attributeOption */
  181.                 foreach ($allKeyboardLanguages as $attributeOption) {
  182.                     if (!isset($data['secondaryOptions'][$key]['options'][$attributeOption->getId()])) {
  183.                         $attrOptionProductSuggestedPrice = $attrOptionProductVatSuggestedPrice = 0;
  184.                         $attrOptionProduct = $attributeOption->getProduct();
  185.                         if ($domain->getType() == Domain::TYPE_WHOLESALE) {
  186.                             if ($attrOptionProduct) {
  187.                                 $attrOptionProductPriceMeta = $attrOptionProduct->getDomainMeta($domain);
  188.                                 if ($attrOptionProductPriceMeta->getDomainSuggestedPrice() > 0 && $attrOptionProductPriceMeta->getDomainVatSuggestedPrice() > 0) {
  189.                                     $attrOptionProductSuggestedPrice = $attrOptionProductPriceMeta->getDomainSuggestedPrice();
  190.                                     $attrOptionProductVatSuggestedPrice = $attrOptionProductPriceMeta->getDomainVatSuggestedPrice();
  191.                                 }
  192.                             }
  193.                             if ($attrOptionProductSuggestedPrice === 0 && $attrOptionProductVatSuggestedPrice === 0) {
  194.                                 $attrOptionRetailPriceMeta = $attributeOption->getDomainMeta($this->getMultiStoreHelper($request)->getRetailDomainByWholesaleDomain());
  195.                                 $attrOptionProductSuggestedPrice = $attrOptionRetailPriceMeta->getDomainPrice();
  196.                                 $attrOptionProductVatSuggestedPrice = $attrOptionRetailPriceMeta->getDomainVatPrice();
  197.                             }
  198.                         }
  199.                         $attrOptionPriceMeta = $attributeOption->getDomainMeta($domain);
  200.                         if ($attrOptionPriceMeta) {
  201.                             $data['secondaryOptions'][$key]['options'][$attributeOption->getId()] = [
  202.                                 'id'                => $attributeOption->getId(),
  203.                                 'title'             => $attributeOption->getTitle(),
  204.                                 'discounted'        => $attrOptionPriceMeta->isDiscounted(),
  205.                                 'price'             => $attrOptionPriceMeta->getDomainPrice(),
  206.                                 'vatPrice'          => $attrOptionPriceMeta->getDomainVatPrice(),
  207.                                 'discount'          => $attrOptionPriceMeta->getDomainDiscount(),
  208.                                 'vatDiscounted'     => $attrOptionPriceMeta->getDomainVatDiscount(),
  209.                                 'suggestedPrice'    => $attrOptionProductSuggestedPrice,
  210.                                 'vatSuggestedPrice' => $attrOptionProductVatSuggestedPrice,
  211.                                 'productId'         => $attributeOption->getProduct() != null ? $attributeOption->getProduct()->getId() : 0,
  212.                                 'image'             => $attrOptionProduct?->getAlbum()?->getNthPhoto()
  213.                                     ? $this->getImage($attrOptionProduct?->getAlbum()?->getNthPhoto(), '')
  214.                                         ->resize(
  215.                                             Image::PRODUCT_CONFIGURATOR_ITEM_THUMB_WIDTH,
  216.                                             Image::PRODUCT_CONFIGURATOR_ITEM_THUMB_HEIGHT
  217.                                         )
  218.                                     : $this->getImage('placeholder.png', '')
  219.                                         ->resize(
  220.                                             Image::PRODUCT_CONFIGURATOR_ITEM_THUMB_WIDTH,
  221.                                             Image::PRODUCT_CONFIGURATOR_ITEM_THUMB_HEIGHT
  222.                                         )
  223.                             ];
  224.                         }
  225.                     }
  226.                 }
  227.             }
  228.         }
  229.         // Set back to a product link for cart
  230.         $request->getSession()->set('cartBackToProductsLink', $this->url($request)->link('product', [
  231.             'product_id' => $productId,
  232.             'isBazaar'   => $data['isBazaar'] ?? 0
  233.         ]));
  234.         if (!empty($data)) {
  235.             // Default Locale
  236.             $defaultLocale = $multiStore->getDefaultLocale();
  237.             $data['domainType'] = $domain->getType();
  238.             $data['partnerLoginRedirect'] = false;
  239.             if (!is_null($request->query->get('partner-link')) && $request->query->get('partner-link') == 1 && !$this->getLoginHelper($request)->isLoggedIn()) {
  240.                 $data['partnerLoginRedirectRoute'] = $this->generateUrl('partner_login');
  241.                 $data['partnerLoginRedirect'] = true;
  242.             }
  243.             // Similar Products
  244.             $data['similarProducts'] = $this->getSimiliarProducts($productId, $cache, $domain, $request, $productHelper);
  245.             // Recommended Products
  246.             $data['recommendedProducts'] = $this->getRecommendedProducts($productId, $cache, $domain, $request, $productHelper);
  247.             $deliveryDate = (new DeliveryDate())->getEstimatedDeliveryDate($domainId, $data['isGamer'], in_array('7d', $data['labels']), is_null($data['orderWaitingDays']) ? 0 : $data['orderWaitingDays']);
  248.             $day = $deliveryDate->format('d.m.Y');
  249.             $data['estimated_deliver_date'] = $this->getTranslator()->trans('Estimated deliver is {day}', [
  250.                 'day' => $day,
  251.             ]);
  252.             // Review form
  253.             $data['reviewForm'] = $this->getProductDetailReviewForm($request, $multiStore->getDefaultLanguage(), $productId, $this->getTranslator());
  254.             $data['services_link'] = $this->url($request)->link('page', [
  255.                 'static_id' => $this->getServicesPageLink($defaultLocale),
  256.             ]);
  257.             $data['free_ship_limit'] = $productHelper::getFreeShipLimits()[$domainId]['freeShipLimit'];
  258.             $data['reviewsRedirectLink'] = $data['typeId'] > 0 && $data['qualityStatusId'] > 0;
  259.             //review_list
  260.             if ($data['reviewsRedirectLink']) {
  261.                 $data['reviewLinkWithFilter'] = $this->generateUrl('review_list_' . $defaultLocale) . '?category=' . $data['typeId'] . '&quality=' . $data['qualityStatusId'];
  262.             }
  263.             // Price Monitor
  264.             $loggedInCustomerId = $request->getSession()->get('customerId');
  265.             $data['isLoggedIn'] = !is_null($loggedInCustomerId) && is_numeric($loggedInCustomerId);
  266.             $data['customer'] = $data['isLoggedIn'] ? $entityManager->getRepository(Customer::class)->findOneById($loggedInCustomerId) : null;
  267.             $identifier = hash('sha512', $request->getClientIp() . $request->server->get('HTTP_USER_AGENT'), false);
  268.             $data['warrantyYear'] = $this->getWarrantyForProductType($domainId, $data['typeId'])['year'];
  269.             $data['priceWarrantyDay'] = $this->getWarrantyForProductType($domainId, $data['typeId'])['priceWarrantyDay'];
  270.             $data['benefitList'] = ['warranty'];
  271.             $data['benefitList'][] = 'payback';
  272.             if ($multiStore->getCustomerTypeId() == Multistore::CUSTOMER_TYPE_RETAIL) {
  273.                 $data['benefitList'][] = 'price-guarantee';
  274.             }
  275.             if (in_array($data['typeId'], [116, 60, 52])) { // AIO, PC, NB
  276.                 $data['benefitList'][] = 'configuration';
  277.             }
  278.             $categoryShortTitle = null;
  279.             $seoUrlHelper = $this->getSeoUrlHelper($request);
  280.             switch ($defaultLocale) {
  281.                 case 'sk':
  282.                     $mainCategoryIds = [
  283.                         'pc' => CategoryPage::SK_CATEGORYPAGE_ID_PC,
  284.                         'nb' => CategoryPage::SK_CATEGORYPAGE_ID_NOTEBOOK,
  285.                         'monitor' => CategoryPage::SK_CATEGORYPAGE_ID_MONITOR,
  286.                     ];
  287.                     break;
  288.                 case 'hu':
  289.                     $mainCategoryIds = [
  290.                         'pc' => CategoryPage::HU_CATEGORYPAGE_ID_PC,
  291.                         'nb' => CategoryPage::HU_CATEGORYPAGE_ID_NOTEBOOK,
  292.                         'monitor' => CategoryPage::HU_CATEGORYPAGE_ID_MONITOR,
  293.                     ];
  294.                     break;
  295.                 case 'cz':
  296.                     $mainCategoryIds = [
  297.                         'pc' => CategoryPage::CZ_CATEGORYPAGE_ID_PC,
  298.                         'nb' => CategoryPage::CZ_CATEGORYPAGE_ID_NOTEBOOK,
  299.                         'monitor' => CategoryPage::CZ_CATEGORYPAGE_ID_MONITOR,
  300.                     ];
  301.                     break;
  302.                 case 'en':
  303.                     $mainCategoryIds = [
  304.                         'pc' => CategoryPage::EU_CATEGORYPAGE_ID_PC,
  305.                         'nb' => CategoryPage::EU_CATEGORYPAGE_ID_NOTEBOOK,
  306.                         'monitor' => CategoryPage::EU_CATEGORYPAGE_ID_MONITOR,
  307.                     ];
  308.                     break;
  309.             }
  310.             $categoryLinkWithBrandFilter = false;
  311.             switch ($data['typeId']) {
  312.                 case 116:
  313.                 case 60:
  314.                     $categoryShortTitle = 'pc';
  315.                     $categoryLinkWithBrandFilter = $seoUrlHelper->link('category', [
  316.                         'path' => $mainCategoryIds[$categoryShortTitle],
  317.                     ]);
  318.                     break;
  319.                 case 52:
  320.                     $categoryShortTitle = 'nb';
  321.                     $categoryLinkWithBrandFilter = $seoUrlHelper->link('category', [
  322.                         'path' => $mainCategoryIds[$categoryShortTitle],
  323.                     ]);
  324.                     break;
  325.                 case 44:
  326.                     $categoryShortTitle = 'monitor';
  327.                     $categoryLinkWithBrandFilter = $seoUrlHelper->link('category', [
  328.                         'path' => $mainCategoryIds[$categoryShortTitle],
  329.                     ]);
  330.                     break;
  331.             }
  332.             if ($categoryShortTitle != null) {
  333.                 $data['benefitList'][] = 'power-cable-' . $categoryShortTitle;
  334.             }
  335.             $data['categoryLinkWithBrandFilter'] = $categoryLinkWithBrandFilter ? $categoryLinkWithBrandFilter . '?fv=' . $data['vendorId'] : null;
  336.             $data['isPriceMonitorActivated'] = $productHelper->isPriceMonitorActivated($productId, $data['customer'], $identifier);
  337.             $data['priceMonitorEmailDictionary'] = json_encode(TextHelper::dictionaryEmail());
  338.             $data['header'] = $this->getHeader($request);
  339.             $data['footer'] = $this->getFooter($request);
  340.             $data['showAdminLoginPanel'] = $request->getSession()->get('isAdminLogin');
  341.             $data['hasStockItemAlbum'] = $data['qualityStatusId'] == Product::QualityStatus_Bazaar ? $entityManager->getRepository(Product::class)->hasStockItemAlbum($productId, $data['isContainer']) : false;
  342.             $data['loggedInCustomer'] = $this->getLoginHelper($request)->getLoggedInCustomer();
  343.             // Shipping Methods
  344.             $data['shippingMethods'] = [];
  345.             $shippingMethods = $entityManager->getRepository(DomainShippingType::class)->findBy([
  346.                 'domain' => $domainId,
  347.                 'activeOnWeb' => true,
  348.             ], [
  349.                 'sortIndex' => 'ASC',
  350.             ]);
  351.             $translator = $this->getTranslator();
  352.             $maxShippingPrice = 0;
  353.             $minShippingPrice = array_key_exists(0, $shippingMethods) ? $shippingMethods[0]->getPrice() : 0;
  354.             foreach ($shippingMethods as $shippingMethod) {
  355.                 if ($shippingMethod->getType() == DomainShippingType::ShippingType_Carrier_Id && $domainId == Domain::DOMAIN_ID_WS_HU) {
  356.                     $translationKey = 'shipping.method.type.' . $shippingMethod->getType() . '.achu';
  357.                 } else {
  358.                     $translationKey = 'shipping.method.type.' . $shippingMethod->getType();
  359.                 }
  360.                 if (($title = $translator->trans($translationKey)) == $translationKey) {
  361.                     $title = false;
  362.                 }
  363.                 if (($description = $translator->trans($translationKey . '.description')) == $translationKey . '.description') {
  364.                     $description = false;
  365.                 }
  366.                 if (($icon = $translator->trans($translationKey . '.icon')) == $translationKey . '.icon') {
  367.                     $icon = false;
  368.                 }
  369.                 $shippingPrice = $shippingMethod->getPrice();
  370.                 if (in_array($domainId, [Domain::DOMAIN_ID_RT_HU, Domain::DOMAIN_ID_WS_HU])) {
  371.                     $shippingPrice = number_format($shippingPrice, 0, '.', '');
  372.                 }
  373.                 $minShippingPrice = $shippingPrice < $minShippingPrice && $shippingPrice > 0 ? $shippingPrice : $minShippingPrice;
  374.                 $maxShippingPrice = $shippingPrice > $maxShippingPrice ? $shippingPrice : $maxShippingPrice;
  375.                 if ($title) {
  376.                     $data['shippingMethods'][$shippingMethod->getId()] = [
  377.                         'id' => $shippingMethod->getId(),
  378.                         'type' => $shippingMethod->getType(),
  379.                         'title' => $title,
  380.                         'description' => $description,
  381.                         'price' => $shippingPrice,
  382.                         'icon' => $icon,
  383.                         'deliveryDays' => $shippingMethod->getShippingDays(),
  384.                         'restriction' => isset($this->paymentMethodRestriction[$shippingMethod->getType()]) ? $this->paymentMethodRestriction[$shippingMethod->getType()] : [],
  385.                     ];
  386.                 }
  387.             }
  388.             $data['minShippingPrice'] = $minShippingPrice;
  389.             $data['maxShippingPrice'] = $maxShippingPrice;
  390.             $data['currencyForShippingRate'] = $data['addressCountry'] = '';
  391.             switch ($defaultLocale) {
  392.                 case 'sk':
  393.                     $data['currencyForShippingRate'] = 'EUR';
  394.                     $data['addressCountry'] = 'SK';
  395.                     break;
  396.                 case 'cz':
  397.                     $data['currencyForShippingRate'] = 'CZK';
  398.                     $data['addressCountry'] = 'CZ';
  399.                     break;
  400.                 case 'hu':
  401.                     $data['currencyForShippingRate'] = 'HUF';
  402.                     $data['addressCountry'] = 'HU';
  403.                     break;
  404.                 default:
  405.                     $data['currencyForShippingRate'] = 'EUR';
  406.                     $data['addressCountry'] = 'EU';
  407.                     $data['minShippingPrice'] = 0;
  408.                     break;
  409.             }
  410.             // Last Update
  411.             if ($productCacheTimeItem->isHit()) {
  412.                 $timestamp = $productCacheTimeItem->get();
  413.                 $data['lastCacheUpdate'] = (new \DateTime())->setTimestamp($timestamp);
  414.             }
  415.             $data['labelOs'] = $this->getProductHelper($request)->getOSLabel($data);
  416.             $data['shippingTitle'] = '';
  417.             $data['shippingCost'] = 0;
  418.             $dataForLowestShippingPriceFunction = [
  419.                 'domain' => $domain,
  420.                 'subTotal' => 0,
  421.                 'packetaCodLimit' => Packeta::getCodLimitByDomainMarketCode(strtoupper($domain->getLanguage()->getCode())),
  422.             ];
  423.             $shippingMethodWithLowestPrice = CartHelper::getShippingMethodWithLowestPriceForDomain($dataForLowestShippingPriceFunction, $entityManager);
  424.             if ($shippingMethodWithLowestPrice) {
  425.                 // Shipping Cost
  426.                 $data['shippingCost'] = $shippingMethodWithLowestPrice->getPrice();
  427.                 // Lowest shipping Name
  428.                 $data['shippingTitle'] = str_replace("(%address%)", "", $translator->trans("shipping.method.type." . $shippingMethodWithLowestPrice->getType()));
  429.                 // Free Shipping
  430.                 if ((float)$shippingMethodWithLowestPrice->getFreeShipLimit() > 0 && (float)$shippingMethodWithLowestPrice->getFreeShipLimit() < $data['subTotal']) {
  431.                     $data['shippingCost'] = 0;
  432.                 }
  433.             }
  434.             // Payment Methods
  435.             $paymentData = $this->getOrderHelper($request)->getPaymentMethodData($domain->getId());
  436.             $data['paymentMethods'] = $paymentData['paymentList'];
  437.             // Sales Manager
  438.             $salesManagerCacheKey = 'product.v3.salesManager.' . $domainId;
  439.             $salesManagerCacheItem = $cache->getItem($salesManagerCacheKey);
  440.             if ($salesManagerCacheItem->isHit()) {
  441.                 $data['salesManager'] = $salesManagerCacheItem->get();
  442.             } else {
  443.                 $webshopPhoneNumber = $this->getContactInfos()['phone.webshop.' . $domain->getLanguage()->getCode() . '.' . $domain->getType()];
  444.                 $data['salesManager'] = $this->getProductHelper($request)->getSalesManagerForProductShow($defaultLocale, $webshopPhoneNumber, $data['salesManager']);
  445.                 $salesManagerCacheItem->set($data['salesManager']);
  446.                 $salesManagerCacheItem->expiresAfter(self::CACHE_LIFETIME_7_DAYS);
  447.                 $cache->save($salesManagerCacheItem);
  448.             }
  449.             $productRepo = $entityManager->getRepository(Product::class);
  450.             $productRepo->getCpuGrouppedProductUAttributeArray($data['attributes']);
  451.             $data['storageAttributeIds'] = [
  452.                 Attribute::ATTRIBUTE_ID_SSD,
  453.                 Attribute::ATTRIBUTE_ID_HDD18,
  454.                 Attribute::ATTRIBUTE_ID_HDD_25,
  455.                 Attribute::ATTRIBUTE_ID_HDD_35,
  456.                 Attribute::ATTRIBUTE_ID_SSHD25,
  457.                 Attribute::ATTRIBUTE_ID_SSHD35,
  458.                 Attribute::ATTRIBUTE_ID_SAS_HDD25,
  459.             ];
  460.             $data['cetelem_hu_shop_id'] = $this->getParameter('cetelem_hu_shop_id');
  461.             $data['cetelem_hu_url'] = $this->getParameter('cetelem_hu_url');
  462.             $data['cetelem_hu_barem_code'] = $this->getParameter('cetelem_hu_barem_code');
  463.             $data['cetelem_hu_price_minimum'] = $this->getParameter('cetelem_hu_price_minimum');
  464.             $priceToPay = $data['special'] ?: $data['price'];
  465.             $data['showKlarna'] = false;
  466.             if (in_array($domainId, [
  467.                 Domain::DOMAIN_ID_RT_SK,
  468.                 Domain::DOMAIN_ID_RT_HU,
  469.                 Domain::DOMAIN_ID_RT_CZ,
  470.                 Domain::DOMAIN_ID_RT_EU,
  471.             ])) {
  472.                 $data['showKlarna'] = $this->getKlarna($domainId, $request)->priceIsWithinRange($data['special'] ?: $data['price']);
  473.             }
  474.             if (in_array($domain->getLanguage()->getCode(), ['hu']) && $this->getEnvironment() == 'prod') {
  475.                 // Milpay
  476.                 $milpayHelper = $this->getMilpay($domain->getLanguage()->getCode());
  477.                 $data['milpayInfo'] = $milpayHelper->getInfoForProductShow($data['special'] ?: $data['price'], $domain);
  478.                 if (!empty($data['milpayInfo'])) {
  479.                     $data['milpayInfo']['staticpageUrl'] = $this->url($request)->link('page', [
  480.                         'static_id' =>  match($domainId) {
  481.                             Domain::DOMAIN_ID_RT_SK => 157,
  482.                             Domain::DOMAIN_ID_RT_HU => 150,
  483.                             Domain::DOMAIN_ID_RT_CZ => 169,
  484.                         }
  485.                     ]);
  486.                     $milpayOfferInfo = $milpayHelper->getAvailableOffers();
  487.                     $milpayOfferId = $milpayOfferInfo['offerId'];
  488.                     $milpayOfferMerchantId = $milpayOfferInfo['merchantId'];
  489.                     $linkHeadingTitle = str_replace([' ', '"'], ['+', "+inch"], $data['heading_title']);
  490.                     $linkDescription = str_replace([' ', '"'], ['+', '+inch'], $data['description']);
  491.                     $linkDescription = str_replace(
  492.                         ['Gold', 'Silver', 'Bronze', 'New', 'Bazaar'],
  493.                         [
  494.                             $translator->trans('grades.A'),
  495.                             $translator->trans('grades.B'),
  496.                             $translator->trans('grades.C'),
  497.                             $translator->trans('grades.New'),
  498.                             $translator->trans('grades.Bazaar'),
  499.                         ],
  500.                         $linkDescription
  501.                     );
  502.                     $data['milpayInfo']['minAmount'] = $milpayOfferInfo['minAmount'];
  503.                     $data['milpayInfo']['maxAmount'] = $milpayOfferInfo['maxAmount'];
  504.                     $redirectUrl = $seoUrlHelper->link('product', [
  505.                         'product_id' => $productId,
  506.                         'isBazaar'   => $data['isBazaar'] ?? 0
  507.                     ]);
  508.                     $priceToPay = $data['special'] ?: $data['price'];
  509.                     $data['milpayInfo']['prescoreLink'] = $milpayHelper->getPrescoreUrl(
  510.                         $domain->getLanguage()->getCode(),
  511.                         $milpayOfferId,
  512.                         $priceToPay,
  513.                         $milpayOfferMerchantId,
  514.                         $linkHeadingTitle,
  515.                         $linkDescription,
  516.                         $redirectUrl
  517.                     );
  518.                 }
  519.             }
  520.             $data['domainId'] = $domainId;
  521.             $data['specificationList'] = $productHelper->getFullSpecificationList($data, $translator, $this->generateUrl("review_list_{$request->getLocale()}"));
  522.             $storageSpec = $this->parseSizeToGb($productHelper->getSSDSize($data['attributes']));
  523.             $data['secondaryOptions'] = array_map(function ($item) use ($storageSpec)  {
  524.                if (str_contains($item['title'], 'SSD')) {
  525.                    $item['options'] = array_filter(
  526.                        $item['options'],
  527.                        function ($option) use ($storageSpec) {
  528.                            $optionSizeGb = $this->parseSizeToGb($option['title']);
  529.                            return $optionSizeGb !== null && $optionSizeGb > $storageSpec;
  530.                        }
  531.                    );
  532.                }
  533.                return $item;
  534.             }, $data['secondaryOptions']);
  535.             if (in_array($domain->getId(), MultiStore::getRetailDomainIDs())
  536.                 && $data['labelOs']['filename'] != 'chrome'
  537.                 && in_array($data['typeId'], [
  538.                     ProductType::PRODUCT_TYPE_ID_PC,
  539.                     ProductType::PRODUCT_TYPE_ID_NOTEBOOK,
  540.                     ProductType::PRODUCT_TYPE_ID_ALL_IN_ONE,
  541.                     ProductType::PRODUCT_TYPE_ID_PHONE,
  542.                     ProductType::PRODUCT_TYPE_ID_SMARTPHONE,
  543.                     ProductType::PRODUCT_TYPE_ID_TABLET,
  544.                     ProductType::PRODUCT_TYPE_ID_PC_SET,
  545.                 ]))
  546.             {
  547.                 $data['showNorton'] = true;
  548.                 $data['nortonUrl'] = match($domainId){
  549.                     Domain::DOMAIN_ID_RT_SK => 'https://www.furbify.sk/norton-360-standard',
  550.                     Domain::DOMAIN_ID_RT_HU => 'https://www.furbify.hu/norton-360-standard',
  551.                     Domain::DOMAIN_ID_RT_CZ => 'https://www.furbify.cz/norton-360-standard',
  552.                     Domain::DOMAIN_ID_RT_EU => 'https://www.furbify.eu/norton-360-standard',
  553.                 };
  554.             }
  555.             //Free packeta shipping
  556.             if ($data['typeId'] == ProductType::PRODUCT_TYPE_ID_NOTEBOOK
  557.                 && !in_array($domainId, [Domain::DOMAIN_ID_RT_EU, Domain::DOMAIN_ID_WS_EU])
  558.                 && (new \DateTime('NOW'))->format('Y-m-d') >= '2025-05-19'
  559.                 && (new \DateTime('NOW'))->format('Y-m-d') <= '2025-06-30')
  560.             {
  561.                 $data['freePacketaShipping'] = true;
  562.             }
  563.             if ($domain->getId() == Domain::DOMAIN_ID_RT_HU) {
  564.                 $packageFeeProduct = $entityManager->getRepository(Product::class)->find(Product::MPL_PACKAGE_FEE_PRODUCT_ID);
  565.                 $data['MPL_PACKAGE_FEE'] = $packageFeeProduct->getDomainMeta($domain)->getCurrentVatPrice();
  566.             }
  567.             return $this->render('AtechNetCoreBundle/Product/product.html.twig', $data);
  568.         }
  569.         return $this->redirectToRoute('not_found');
  570.     }
  571.     /**
  572.      * @param int $productId
  573.      * @param Request $request
  574.      * @param Domain $domain
  575.      * @param $entityManager
  576.      * @param MultiStore $multiStore
  577.      * @throws \Psr\SimpleCache\InvalidArgumentException
  578.      */
  579.     private function getProductViewData(int $productId, Request $request, Domain $domain, $entityManager, MultiStore $multiStore)
  580.     {
  581.         $product = $this->getProductHelper($request)->getStructuredDataByProductId($productId);
  582.         if ($product) {
  583.             return $this->buildProductViewData($product, $request, $domain, $entityManager, $multiStore);
  584.         }
  585.         return false;
  586.     }
  587.     /**
  588.      * @param $product
  589.      * @param Request $request
  590.      * @param Domain $domain
  591.      * @param $entityManager
  592.      * @param MultiStore $multiStore
  593.      * @return array
  594.      * @throws \Exception
  595.      */
  596.     private function buildProductViewData($product, Request $request, Domain $domain, $entityManager, MultiStore $multiStore): array
  597.     {
  598.         $seoUrlHelper = $this->getSeoUrlHelper($request);
  599.         $translator = $this->getTranslator();
  600.         $data = [];
  601.         $data['currency'] = $domain->getCurrency();
  602.         $data['currency_ISO'] = $this->getCurrencyISOForm($data['currency']);
  603.         $data['precision'] = $domain->getPricePrecision();
  604.         $data['vatPercentage'] = $domain->getVat();
  605.         $data['breadcrumbs'] = [];
  606.         $data['breadcrumbs'][] = $this->getBreadCrumbsBase($request);
  607.         // Category Repository
  608.         $categoryPageRepository = $entityManager->getRepository(CategoryPage::class);
  609.         $categoryPageRepository->setSession($request->getSession());
  610.         switch ($domain->getId()) {
  611.             case Domain::DOMAIN_ID_WS_SK:
  612.                 $categoryDomain = $entityManager->getRepository(Domain::class)->findOneBy([
  613.                     'id' => Domain::DOMAIN_ID_RT_SK,
  614.                 ]);
  615.                 break;
  616.             case Domain::DOMAIN_ID_WS_HU:
  617.                 $categoryDomain = $entityManager->getRepository(Domain::class)->findOneBy([
  618.                     'id' => Domain::DOMAIN_ID_RT_HU,
  619.                 ]);
  620.                 break;
  621.             case Domain::DOMAIN_ID_WS_CZ:
  622.                 $categoryDomain = $entityManager->getRepository(Domain::class)->findOneBy([
  623.                     'id' => Domain::DOMAIN_ID_RT_CZ,
  624.                 ]);
  625.                 break;
  626.             case Domain::DOMAIN_ID_WS_EU:
  627.                 $categoryDomain = $entityManager->getRepository(Domain::class)->findOneBy([
  628.                     'id' => Domain::DOMAIN_ID_RT_EU,
  629.                 ]);
  630.                 break;
  631.             default:
  632.                 $categoryDomain = $domain;
  633.                 break;
  634.         }
  635.         $productMainCategoryPage = $entityManager
  636.             ->createQuery("SELECT cp
  637.                 FROM AtechNetCoreBundle:CategoryPage cp
  638.                 LEFT JOIN cp.productTypes pt
  639.                 LEFT JOIN cp.vendors v
  640.                 WHERE pt.id = :productTypeId AND v.id IS NULL AND cp.domain = :domain AND cp.showOnlyBazaar = :bazaar")
  641.             ->setParameters([
  642.                 'productTypeId' => $product['productTypeId'], 
  643.                 'domain'        => $categoryDomain, 
  644.                 'bazaar'        => $request->getSession()->get('isBazaarPage')
  645.             ])
  646.             ->setMaxResults(1)
  647.             ->getResult();
  648.         if (isset($productMainCategoryPage[0])) {
  649.             $categoryPage = $productMainCategoryPage[0];
  650.             $categoryPageMeta = $categoryPage->getMetaByLanguage($multiStore->getDefaultLanguage());
  651.             if ($categoryPageMeta) {
  652.                 $useAlternativeCategoryPage = false;
  653.                 if ($multiStore->isLanguageSwitched()) {
  654.                     $alternativeCategoryPage = $categoryPageRepository->getAlternativeCategoryByLanguage($categoryPage);
  655.                     if ($alternativeCategoryPage) {
  656.                         $alternativeCategoryMeta = $alternativeCategoryPage->getMetaByLanguage($multiStore->getLanguage());
  657.                         if ($alternativeCategoryMeta) {
  658.                             $useAlternativeCategoryPage = true;
  659.                             $data['breadcrumbs'][] = [
  660.                                 'text' => $alternativeCategoryMeta->getTitle(),
  661.                                 'href' => $seoUrlHelper->link('category', [
  662.                                     'path'      => $categoryPage->getId(), 
  663.                                     'isBazaar'  => $categoryPage->isShowOnlyBazaar()
  664.                                 ])
  665.                             ];
  666.                         }
  667.                     }
  668.                 }
  669.                 if ( $useAlternativeCategoryPage === false ) {
  670.                     $data['breadcrumbs'][] = [
  671.                         'text' => $categoryPageMeta->getTitle(),
  672.                         'href' => $seoUrlHelper->link('category', [
  673.                             'path'      => $categoryPage->getId(), 
  674.                             'isBazaar'  => $categoryPage->isShowOnlyBazaar()
  675.                         ]),
  676.                     ];
  677.                 }
  678.             }
  679.         }
  680.         $data['breadcrumbs'][] = [
  681.             'text' => ($product['vendor'] !== '' ? $product['vendor'] . ' ' : '') . $product['title'],
  682.             'href' => $this->url($request)->link('product', [
  683.                 'product_id' => $product['id'],
  684.                 'isBazaar'   => $product['isBazaar'] ?? 0
  685.             ]),
  686.         ];
  687.         $data['heading_title'] = ($product['vendor'] !== '' ? $product['vendor'] . ' ' : '') . ProductHelper::getHeadingTitle($product);
  688.         $data['h1_title'] = ($multiStore->getCustomerTypeId() == MultiStore::CUSTOMER_TYPE_RETAIL) ?
  689.             ($product['vendor'] !== '' ? $product['vendor'] . ' ' : '') . ProductHelper::getLongTitleWithConfig($product, $translator) :
  690.             $product['title'] . ' - ' . $product['code'];
  691.         $data['h1_title'] = in_array($domain->getId(), [Domain::DOMAIN_ID_RT_EU, Domain::DOMAIN_ID_WS_EU]) ? str_replace([' (Quality: Bazar)', ' (Quality: Bazár)', ' (Quality: Bazár, '], ['', '', ' ('], $data['h1_title']) : $data['h1_title'];
  692.         $data['seoDescription'] = ($product['shortDescription'] != '' ? $product['shortDescription'] : $data['heading_title']) . ' | ' . $product['code'];
  693.         $data['product_id'] = $product['id'];
  694.         $data['title'] = $product['vendor'] . ' ' . $product['title'];
  695.         $data['productName'] = $product['title'];
  696.         $data['type'] = $product['productType'];
  697.         $data['typeId'] = $product['productTypeId'];
  698.         $data['product_type_id'] = $product['productTypeId'];
  699.         $data['model'] = $product['code'];
  700.         $data['partNumber'] = $product['partNumber'];
  701.         $data['available'] = $product['availableQty'];
  702.         $data['orderWaitingDays'] = $product['orderWaitingDays'];
  703.         $data['description'] = str_replace(' | ', ', ', $product['shortDescription']);
  704.         $data['quality'] = $product['qualityTitle'];
  705.         $data['qualityStatusId'] = $product['qualityStatusId'];
  706.         $data['active'] = $product['active'];
  707.         $data['timedSalesActive'] = $product['timedSalesActive'];
  708.         $data['timedSalesEndDate'] = $product['timedSalesEndDate'];
  709.         $data['priceWoVAT'] = $product['price'];
  710.         $data['discountWoVAT'] = $product['discountPrice'];
  711.         $data['rawPriceWoVAT'] = $product['rawPrice'];
  712.         $data['rawDiscountPriceWoVAT'] = $product['rawDiscountPrice'];
  713.         $data['weight'] = $product['weight'] != 0 ? number_format($product['weight'] / 1000, 1, ',', ' ') . ' kg' : '';
  714.         $data['isContainer'] = $product['isContainer'];
  715.         $data['containerParts'] = $product['containerParts'];
  716.         $data['connectedBatteries'] = $product['connectedBatteries'] ?? [];
  717.         $data['isBazaar'] = $product['isBazaar'] ?? 0;
  718.         $dimensions = [];
  719.         if ($product['width'] != 0) {
  720.             $dimensions[] = $product['width'] . ' mm';
  721.         }
  722.         if ($product['length'] != 0) {
  723.             $dimensions[] = $product['length'] . ' mm';
  724.         }
  725.         if ($product['height'] != 0) {
  726.             $dimensions[] = $product['height'] . ' mm';
  727.         }
  728.         $data['dimensions'] = !empty($dimensions) ? implode(' x ', $dimensions) : '';
  729.         $data['additionalDetail'] = ProductHelper::createFormatedDetail($product['additionalDetail']);
  730.         switch ($domain->getId()) {
  731.             case Domain::DOMAIN_ID_RT_SK:
  732.             case Domain::DOMAIN_ID_WS_SK:
  733.                 $data['quality_descriptions_link'] = $seoUrlHelper->link('page', [
  734.                     'static_id' => 11,
  735.                 ]);
  736.                 $data['shipping_info_link'] = $seoUrlHelper->link('page', [
  737.                     'static_id' => 14,
  738.                 ]);
  739.                 $data['price_guarantee_link'] = $seoUrlHelper->link('page', [
  740.                     'static_id' => 41,
  741.                 ]);
  742.                 $data['cetelem_desc_page_link'] = $seoUrlHelper->link('page', [
  743.                     'static_id' => 16,
  744.                 ]);
  745.                 break;
  746.             case Domain::DOMAIN_ID_RT_HU:
  747.             case Domain::DOMAIN_ID_WS_HU:
  748.                 $data['quality_descriptions_link'] = $seoUrlHelper->link('page', [
  749.                     'static_id' => 27,
  750.                 ]);
  751.                 $data['shipping_info_link'] = $seoUrlHelper->link('page', [
  752.                     'static_id' => 30,
  753.                 ]);
  754.                 $data['price_guarantee_link'] = $seoUrlHelper->link('page', [
  755.                     'static_id' => 40,
  756.                 ]);
  757.                 $data['cetelem_desc_page_link'] = $seoUrlHelper->link('page', [
  758.                     'static_id' => 19,
  759.                 ]);
  760.                 break;
  761.             case Domain::DOMAIN_ID_RT_CZ:
  762.             case Domain::DOMAIN_ID_WS_CZ:
  763.                 $data['quality_descriptions_link'] = $seoUrlHelper->link('page', [
  764.                     'static_id' => 60,
  765.                 ]);
  766.                 $data['shipping_info_link'] = $seoUrlHelper->link('page', [
  767.                     'static_id' => 63,
  768.                 ]);
  769.                 $data['price_guarantee_link'] = $seoUrlHelper->link('page', [
  770.                     'static_id' => 67,
  771.                 ]);
  772.                 $data['cetelem_desc_page_link'] = $seoUrlHelper->link('page', [
  773.                     'static_id' => 65,
  774.                 ]);
  775.                 break;
  776.             default:
  777.                 $data['quality_descriptions_link'] = $seoUrlHelper->link('page', [
  778.                     'static_id' => 11,
  779.                 ]);
  780.                 $data['shipping_info_link'] = $seoUrlHelper->link('page', [
  781.                     'static_id' => 14,
  782.                 ]);
  783.                 $data['price_guarantee_link'] = $seoUrlHelper->link('page', [
  784.                     'static_id' => 41,
  785.                 ]);
  786.                 $data['cetelem_desc_page_link'] = $seoUrlHelper->link('page', [
  787.                     'static_id' => 16,
  788.                 ]);
  789.         }
  790.         if ($data['quality']) {
  791.             switch ($data['quality']) {
  792.                 case 'New':
  793.                     $data['quality_description'] = $translator->trans('quality description new');
  794.                     break;
  795.                 case 'Gold':
  796.                     $data['quality_description'] = $translator->trans('quality description gold');
  797.                     break;
  798.                 case 'Silver':
  799.                     $data['quality_description'] = $translator->trans('quality description silver');
  800.                     break;
  801.                 case 'Bronze':
  802.                     $data['quality_description'] = $translator->trans('quality description bronze');
  803.                     break;
  804.                 case 'Platinum':
  805.                     $data['quality_description'] = $translator->trans('quality description platinum');
  806.                     break;
  807.                 default:
  808.                     $data['quality_description'] = '';
  809.             }
  810.         }
  811.         $data['brand'] = $product['vendor'];
  812.         $data['vendorId'] = $product['vendorId'];
  813.         $data['orderable'] = (int)$product['orderable'];
  814.         $data['price'] = $product['vatPrice'];
  815.         $data['suggestedVatPrice'] = $product['suggestedVatPrice'];
  816.         $data['suggestedPrice'] = $product['suggestedPrice'];
  817.         $data['profitPercentage'] = 0;
  818.         $data['isDiscounted'] = $product['isDiscounted'];
  819.         if ($product['isDiscounted']) {
  820.             $data['discountWithVat'] = $product['discountVatPrice'];
  821.             $data['special'] = $product['discountVatPrice'];
  822.             if ($product['discountVatPrice'] != 0 && $data['suggestedVatPrice'] != 0) {
  823.                 $data['profitPercentage'] = round((1 - ($data['special'] / $data['suggestedVatPrice'])) * 100, 0);
  824.             }
  825.         } else {
  826.             $data['special'] = false;
  827.             if ($product['vatPrice'] != 0 && $data['suggestedVatPrice'] != 0) {
  828.                 $data['profitPercentage'] = round((1 - ($data['price'] / $data['suggestedVatPrice'])) * 100, 0);
  829.             }
  830.         }
  831.         $data['images'] = [];
  832.         if (count($product['images']) > 0) {
  833.             foreach ($product['images'] as $photo) {
  834.                 $data['images'][] = [
  835.                     'popup' => $this->getImage($photo, 'product/' . $product['code'])->resize(Image::PRODUCT_VIEW_POPUP_WIDTH, Image::PRODUCT_VIEW_POPUP_HEIGHT),
  836.                     'thumb' => $this->getImage($photo, 'product/' . $product['code'])->resize(Image::PRODUCT_VIEW_THUMB_WIDTH, Image::PRODUCT_VIEW_THUMB_HEIGHT),
  837.                     'additional' => $this->getImage($photo, 'product/' . $product['code'])->resize(Image::PRODUCT_VIEW_ADDITIONAL_WIDTH, Image::PRODUCT_VIEW_ADDITIONAL_HEIGHT),
  838.                 ];
  839.             }
  840.             $data['thumb'] = $this->getImage($product['images']->first(), 'product/' . $product['code'])->resize(Image::LIVESEARCH_THUMB_WIDTH, Image::LIVESEARCH_THUMB_HEIGHT);
  841.         } else {
  842.             $placeholder = $this->getImage('placeholder.png', '')->resize(Image::PRODUCT_VIEW_POPUP_WIDTH, Image::PRODUCT_VIEW_POPUP_HEIGHT);
  843.             $data['images'][] = [
  844.                 'popup' => $placeholder,
  845.                 'thumb' => $placeholder,
  846.                 'additional' => $placeholder,
  847.             ];
  848.         }
  849.         $data['labels'] = $product['badges'];
  850.         $data['isBestseller'] = $product['isBestseller'] ?? false;
  851.         $data['options'] = $product['accessories'];
  852.         $data['primaryOptions'] = $data['secondaryOptions'] = [];
  853.         $data['skinColorSelectorIsDefined'] = false;
  854.         if (!empty($product['connectedBatteries'])) {
  855.             /** @var AttributeOption $newBatteryAttributeOption */
  856.             $newBatteryAttributeOption = $entityManager->getRepository(AttributeOption::class)->find($product['batterAttributeOptionId']);
  857.             if ($newBatteryAttributeOption) {
  858.                 $optionMeta = $newBatteryAttributeOption->getDomainMeta($domain);
  859.                 $attributeOptionId = $newBatteryAttributeOption->getId();
  860.                 $defaultData = [
  861.                     'id' => Attribute::ATTRIBUTE_ID_NEW_BATTERY,
  862.                     'title' => $this->translator->trans('New battery'),
  863.                     'options' => [
  864.                         $attributeOptionId => [
  865.                             'id'                => $attributeOptionId,
  866.                             'title'             => $newBatteryAttributeOption->getTitle($this->getDatabaseTranslator($request)),
  867.                             'discounted'        => $optionMeta->isDiscounted(),
  868.                             'vatPrice'          => $optionMeta->getDomainVatPrice(),
  869.                             'price'             => $optionMeta->getDomainPrice(),
  870.                             "discount"          => $optionMeta->getDomainDiscount(),
  871.                             "vatDiscounted"     => $optionMeta->getDomainVatDiscount(),
  872.                             "suggestedPrice"    => $optionMeta->getDomainPrice(),
  873.                             "vatSuggestedPrice" => $optionMeta->getDomainVatPrice(),
  874.                             "productId"         => $newBatteryAttributeOption->getProduct()->getId(),
  875.                             "image"             => 'battery.svg',
  876.                         ],
  877.                     ]
  878.                 ];
  879.                 $data['secondaryOptions'][] = $defaultData;
  880.             }
  881.         }
  882.         foreach ($data['options'] as $option) {
  883.             // Scan $option['options'] for defined product_ids; if it`s true { get product`s first image }
  884.             foreach ($option['options'] as $key => $value) {
  885.                 if (($value['productId'] != 0)) {
  886.                     // image goes here
  887.                     $configurationProduct = $this->getProductHelper($request)->getStructuredDataByProductId($value['productId'], 'configurator');
  888.                     $option['options'][$key]['image'] = $this->getImage($configurationProduct['images'], 'product/' . $value['productId'])->resize(Image::PRODUCT_CONFIGURATOR_ITEM_THUMB_WIDTH, Image::PRODUCT_CONFIGURATOR_ITEM_THUMB_HEIGHT);
  889.                 }
  890.             }
  891.             if (in_array($option['id'], [
  892.                 Attribute::ATTRIBUTE_ID_ACCESSORY_OS,
  893.                 Attribute::ATTRIBUTE_ID_ACCESSORY_SOFTWARE_PACKAGE,
  894.                 Attribute::ATTRIBUTE_ID_ACCESSORY_ANTIVIRUS_SOFTWARE,
  895.                 Attribute::ATTRIBUTE_ID_ACCESSORY_OFFICE_365,
  896.             ])) {
  897.                 if ($option['id'] == Attribute::ATTRIBUTE_ID_ACCESSORY_OS) {
  898.                     if ($multiStore->getCustomerTypeId() == MultiStore::CUSTOMER_TYPE_RETAIL) {
  899.                         unset($option['options'][425]); // MAR windows 10 pro
  900.                         unset($option['options'][426]); // MAR windows 10 home
  901.                     }
  902.                     else {
  903.                         unset($option['options'][2128]); // Windows 10 pro digital
  904.                     }
  905.                 }
  906.                 if (in_array($domain->getId(), [Domain::DOMAIN_ID_RT_EU, Domain::DOMAIN_ID_WS_EU]) && $option['id'] == 23) {
  907.                     foreach ($option['options'] as $antivisOptionKey => $antivirusOption) {
  908.                         if (!str_contains($antivirusOption['title'], 'G DATA')) {
  909.                             unset($option['options'][$antivisOptionKey]);
  910.                         }
  911.                     }
  912.                 }
  913.                 $data['primaryOptions'][] = $option;
  914.             }
  915.             //SKIP POWER CABLE FOR MONITORS
  916.             else if ($product['productTypeId'] == ProductType::PRODUCT_TYPE_ID_MONITOR && $option['id'] == Attribute::ATTRIBUTE_ID_POWER_CABLE) {
  917.                 continue;
  918.             }
  919.             else {
  920.                 $data['secondaryOptions'][] = $option;
  921.                 if ($option['id'] == Attribute::ATTRIBUTE_ID_NOTEBOOK_SKIN) {
  922.                     $data['skinColorSelectorIsDefined'] = true;
  923.                 }
  924.             }
  925.         }
  926.         $installSoftwarePackageOption = null;
  927.         foreach ($data['primaryOptions'] as $key => $option) {
  928.             if ($option['id'] == Attribute::ATTRIBUTE_ID_ACCESSORY_SOFTWARE_PACKAGE) {
  929.                 $installSoftwarePackageOption = $option;
  930.                 unset($data['primaryOptions'][$key]);
  931.             }
  932.             if ($option['id'] == Attribute::ATTRIBUTE_ID_ACCESSORY_OS) {
  933.                 $order = [
  934.                     AttributeOption::ATTRIBUTE_OPTION_ID_WINDOWS_11_PRO,
  935.                     AttributeOption::ATTRIBUTE_OPTION_ID_WINDOWS_11_HOME,
  936.                     AttributeOption::ATTRIBUTE_OPTION_ID_WINDOWS_10_PRO,
  937.                     AttributeOption::ATTRIBUTE_OPTION_ID_WINDOWS_10_HOME,
  938.                     AttributeOption::ATTRIBUTE_OPTION_ID_LINUX_MINT
  939.                 ];
  940.                 uksort($option['options'], function ($a, $b) use ($order) {
  941.                     $posA = array_search($a, $order);
  942.                     $posB = array_search($b, $order);
  943.                     return $posA <=> $posB;
  944.                 });
  945.                 $data['primaryOptions'][$key]['options'] = $option['options'];
  946.             }
  947.         }
  948.         // move to last position
  949.         if ($installSoftwarePackageOption != null) {
  950.             $data['primaryOptions'][] = $installSoftwarePackageOption;
  951.         }
  952.         $data['defaultOptions'] = $product['defaultOptions'];
  953.         $data['attributes'] = $product['attributes'];
  954.         $data['isGamer'] = in_array('gamer', $data['labels']);
  955.         // Includes
  956.         $data['include_cable'] = '';
  957.         if ((int)$product['productTypeId'] == 44) {
  958.             $data['include_cable'] = $translator->trans('Free power cord and data cable included');
  959.         } elseif ((int)$product['productTypeId'] == 52) {
  960.             $data['include_cable'] = $translator->trans('Free AC adapter and power cord included');
  961.         } elseif ((int)$product['productTypeId'] == 116 || (int)$product['productTypeId'] == 60) {
  962.             $data['include_cable'] = $translator->trans('Free power cord included');
  963.         }
  964.         $data['include_keyboard_sticker'] = '';
  965.         if ((int)$product['productTypeId'] == 52) {
  966.             $data['include_keyboard_sticker'] = $translator->trans('Free keyboard sticker included');
  967.         }
  968.         // Ready Box
  969.         $data['show_ready_box'] = in_array($product['productTypeId'], self::READY_BOX_PRODUCT_TYPES) && $data['quality'] != 'New' && $data['brand'] != 'Apple';
  970.         $domainLanguageCode = $domain->getLanguage()->getCode();
  971.         // Cetelem & Quatro
  972.         $data['cetelem_calculator'] = false;
  973.         $data['quatro_calculator'] = false;
  974.         if ($domain->getId() == Domain::DOMAIN_ID_RT_HU) { // LPC or FPC
  975.             $data['cetelem_calculator'] = true;
  976.             $data['cetelem_calculator_country'] = $domainLanguageCode;
  977.         }
  978.         if ($product['isDiscounted']) {
  979.             $productPrice = $domain->getType() == Domain::TYPE_RETAIL ? $data['discountWithVat'] : $data['discountWoVAT'];
  980.         } else {
  981.             $productPrice = $domain->getType() == Domain::TYPE_RETAIL ? $data['price'] : $data['rawPriceWoVAT'];
  982.         }
  983.         if ($domain->getId() == Domain::DOMAIN_ID_RT_SK && $productPrice >= 100) { // LPC
  984.             $data['quatro_calculator'] = $this->getParameter('quatro_calculator_url');
  985.         }
  986.         $data['salesManager'] = [];
  987.         $loggedInCustomer = $this->getLoginHelper($request)->getLoggedInCustomer();
  988.         if (!is_null($loggedInCustomer) && !is_null($loggedInCustomer->getSalesManager())) {
  989.             $salesManager = $loggedInCustomer->getSalesManager();
  990.             $data['salesManager']['id'] = $salesManager->getId();
  991.             $data['salesManager']['username'] = $salesManager->getUsername();
  992.             $data['salesManager']['name'] = $salesManager->getFirstName();
  993.             $data['salesManager']['phone'] = $salesManager->getPhone();
  994.         }
  995.         $data['webshop_phone_number'] = $this->getContactInfos()['phone.webshop.' . $domainLanguageCode . '.' . $domain->getType()];
  996.         $data['contentBottom'] = $this->getContentBottom($request, null, $this->getWarrantyForProductType($domain->getId(), $product['productTypeId'])['year']);
  997.         $data['reviewCount'] = $product['reviewCount'];
  998.         $data['reviewStars'] = $product['reviewStars'];
  999.         $data['reviews'] = $product['reviews'];
  1000.         /**
  1001.          * CHECK IF EXIST A SHIPPING METHOD WITH FREE SHIPPING
  1002.          */
  1003.         $shippingTypes = $entityManager->createQueryBuilder()
  1004.             ->select('dst')
  1005.             ->from('AtechNetCoreBundle:DomainShippingType', 'dst')
  1006.             ->where('dst.domain = :domain')
  1007.             ->andWhere('dst.freeShippingStartDate IS NOT NULL AND dst.freeShippingEndDate IS NOT NULL')
  1008.             ->andWhere('dst.freeShippingStartDate <= :now AND dst.freeShippingEndDate >= :now')
  1009.             ->setParameters([
  1010.                 'domain' => $domain->getId(),
  1011.                 'now' => (new \DateTime())->format('Y-m-d'),
  1012.             ])
  1013.             ->getQuery()
  1014.             ->getResult();
  1015.         $filteredShippingTypes = array_filter($shippingTypes, function ($shippingType) use ($product) {
  1016.             /** @var DomainShippingType $shippingType */
  1017.             return in_array($product['productTypeId'], $shippingType->getFreeShippingProductTypes(), true);
  1018.         });
  1019.         $data['freeShipping'] = count($filteredShippingTypes) > 0;
  1020.         if (!is_null($product['couponCode'])) {
  1021.             $data['coupon'] = [
  1022.                 'id' => $product['couponId'],
  1023.                 'code' => $product['couponCode'],
  1024.                 'discount' => $product['couponDiscount'],
  1025.                 'priceWithCoupon' => $product['vatPriceWithCoupon'],
  1026.                 'showCouponBadgeOnWebsite'=> $product['showCouponBadgeOnWebsite'],
  1027.             ];
  1028.         }
  1029.         if (!is_null($product['productModelDescription'])) {
  1030.             $data['productModelDescription'] = $product['productModelDescription'];
  1031.         }
  1032.         if (!is_null($product['warranties'])) {
  1033.             $data['warranties'] = [];
  1034.             $extendedWarranty = $entityManager->getRepository(Attribute::class)->findOneById(Attribute::ATTRIBUTE_ID_EXTENDED_WARRANTY);
  1035.             $data['warranties']['attribute'] = $extendedWarranty;
  1036.             foreach ($product['warranties'] as $optionId => $warranty) {
  1037.                 $attributeOption = $entityManager->getRepository(AttributeOption::class)->find($optionId);
  1038.                 $warrantyPercent = $warranty['percentPrice'];
  1039.                 //2025 christmas ->
  1040.                 $now = new \DateTime('now');
  1041.                 $startDate = new \DateTime("2025-11-30 00:00:00");
  1042.                 $endDate = new \DateTime("2025-12-21 23:59:59");
  1043.                 $discountWarrantyPercent = $warrantyPercent;
  1044.                 if ($now >= $startDate && $now <= $endDate) {
  1045.                     $discountWarrantyPercent /= 2;
  1046.                 }
  1047.                 $productPrice = $product['isDiscounted'] ? $product['rawDiscountPrice'] : $product['price'];
  1048.                 $productVatPrice = $product['isDiscounted'] ? $product['discountVatPrice'] : $product['vatPrice'];
  1049.                 $data['warranties']['data'][] = [
  1050.                     'id'            => $attributeOption->getId(),
  1051.                     'title'         => $attributeOption->getTitle(),
  1052.                     'vatPrice'      => $domain->createVatPrice((($productVatPrice * $warrantyPercent) / 100), 1.),
  1053.                     'price'         => $domain->createVatPrice((($productPrice * $warrantyPercent) / 100), 1.),
  1054.                     'vatDiscounted' => $domain->createVatPrice((($productVatPrice * $discountWarrantyPercent) / 100), 1.),
  1055.                     'discount'      => $domain->createVatPrice((($productPrice * $discountWarrantyPercent) / 100), 1.),
  1056.                     'image'         => $warranty['image'],
  1057.                 ];
  1058.             }
  1059.         }
  1060.         return $data;
  1061.     }
  1062.     /**
  1063.      * @param int $productId
  1064.      * @param CacheItemPoolInterface $cache
  1065.      * @param Domain $domain
  1066.      * @param Request $request
  1067.      * @param ProductHelper $productHelper
  1068.      * @return array
  1069.      * @throws \Doctrine\ORM\NoResultException
  1070.      * @throws \Doctrine\ORM\NonUniqueResultException
  1071.      */
  1072.     private function getSimiliarProducts($productId, CacheItemPoolInterface $cache, Domain $domain, Request $request, ProductHelper $productHelper)
  1073.     {
  1074.         $similarProductsCacheKey = ProductHelper::getSimiliarProductsCacheKey($domain->getId(), $request->getLocale(), $productId);
  1075.         $similarProductsCacheItem = $cache->getItem($similarProductsCacheKey);
  1076.         if (!$similarProductsCacheItem->isHit()) {
  1077.             $placeholder = $this->getImage('placeholder.png', '')->resize(Image::PRODUCT_LIST_THUMB_WIDTH, Image::PRODUCT_LIST_THUMB_HEIGHT);
  1078.             $similiarProducts = [];
  1079.             foreach ($productHelper->getSimilarProducts($productId) as $similarProduct) {
  1080.                 $image = $placeholder;
  1081.                 if (is_object($similarProduct['images'])) {
  1082.                     $image = $this->getImage($similarProduct['images'], 'product/' . $similarProduct['code'])->resize(Image::PRODUCT_LIST_THUMB_WIDTH, Image::PRODUCT_LIST_THUMB_HEIGHT);
  1083.                 }
  1084.                 $attributeListTxt = in_array(
  1085.                     $similarProduct['productTypeId'],
  1086.                     [ProductType::PRODUCT_TYPE_ID_TABLET, ProductType::PRODUCT_TYPE_ID_SMARTWATCH]
  1087.                 ) ?
  1088.                     str_replace([' | ', 'Win 10 Pro'], [', ', 'Windows'], $similarProduct['shortDescription']) :
  1089.                     str_replace([' | ', 'Win 10 Pro'], [', ', 'Windows'], $similarProduct['attributesListTxt'])
  1090.                 ;
  1091.                 $similiarProducts[] = [
  1092.                     'image' => $image,
  1093.                     'labels' => $similarProduct['badges'],
  1094.                     'vendor' => $similarProduct['vendor'],
  1095.                     'vendorId' => $similarProduct['vendorId'],
  1096.                     'typeId' => $similarProduct['productTypeId'],
  1097.                     'title' => $similarProduct['title'],
  1098.                     'price' => $similarProduct['vatPrice'],
  1099.                     'rawPrice' => $similarProduct['rawPrice'],
  1100.                     'rawDiscountPrice' => $similarProduct['rawDiscountPrice'],
  1101.                     'attributes' => $similarProduct['attributes'],
  1102.                     'available' => $similarProduct['availableQty'],
  1103.                     'special' => ($similarProduct['isDiscounted'] ? $similarProduct['discountVatPrice'] : false),
  1104.                     'href' => $this->url($request)->link('product', [
  1105.                         'product_id' => $similarProduct['id'],
  1106.                         'isBazaar'   => $similarProduct['isBazaar'] ?? 0
  1107.                     ]),
  1108.                     'active' => $similarProduct['active'],
  1109.                     'timedSalesActive' => $similarProduct['timedSalesActive'],
  1110.                     'reviewCount' => $similarProduct['reviewCount'],
  1111.                     'reviewStars' => $similarProduct['reviewStars'],
  1112.                     'reviews' => $similarProduct['reviews'],
  1113.                     'freeShipping' => $similarProduct['freeShipping'],
  1114.                     'attributesListTxt' => $attributeListTxt,
  1115.                     'warrantyYear' => $similarProduct['qualityStatusId'] == Product::QualityStatus_Bazaar ? 1 : $this->getWarrantyForProductType($domain->getId(), $similarProduct['productTypeId'])['year'],
  1116.                     'labelOS' => $this->getProductHelper($request)->getOSLabel($similarProduct),
  1117.                     'qualityStatusTitle' => Product::getQualityStatusChoices()[$similarProduct['qualityStatusId']],
  1118.                 ];
  1119.             }
  1120.             $similarProductsCacheItem->set($similiarProducts);
  1121.             $similarProductsCacheItem->expiresAfter(self::CACHE_LIFETIME_12_HOURS);
  1122.             $cache->save($similarProductsCacheItem);
  1123.             return $similiarProducts;
  1124.         } else {
  1125.             return $similarProductsCacheItem->get();
  1126.         }
  1127.     }
  1128.     /**
  1129.      * @param Request $request
  1130.      * @param $language
  1131.      * @param $productId
  1132.      * @param $translator
  1133.      * @return bool|\Symfony\Component\Form\FormView
  1134.      */
  1135.     public function getProductDetailReviewForm(Request $request, $language, $productId, $translator)
  1136.     {
  1137.         // Reviews
  1138.         if ($this->getLoginHelper($request)->isLoggedIn()) {
  1139.             $review = new Review();
  1140.             $customer = $this->getLoginHelper($request)->getLoggedInCustomer();
  1141.             $form = $this->createForm(ReviewType::class, $review, [
  1142.                 'locale' => $request->getLocale(),
  1143.             ]);
  1144.             if ($customer) {
  1145.                 $name = $customer->getBusinessName();
  1146.                 if ($name == '') {
  1147.                     $name = $customer->getFirstName();
  1148.                 }
  1149.                 $form->get('name')->setData($name);
  1150.             }
  1151.             $form->handleRequest($request);
  1152.             if ($form->isSubmitted() && $form->isValid()) {
  1153.                 $entityManager = $this->getEntityManager();
  1154.                 $review->setName($form->get('name')->getData());
  1155.                 $review->setText($form->get('text')->getData());
  1156.                 $review->setStars($form->get('stars')->getData());
  1157.                 $review->setLanguage($language);
  1158.                 $review->setType(Review::TYPE_PRODUCT);
  1159.                 $review->setApproved(0);
  1160.                 $productObject = $entityManager->getRepository(Product::class)->findOneById($productId);
  1161.                 $review->setProduct($productObject);
  1162.                 if ($customer) {
  1163.                     $review->setCustomer($customer);
  1164.                 }
  1165.                 $entityManager->persist($review);
  1166.                 // Upload Files
  1167.                 $fileCount = 0;
  1168.                 $subDirectory = 'survey-images';
  1169.                 $addedSurveyMedias = [];
  1170.                 $files = $request->files->get('reviewImages');
  1171.                 foreach ($files as $file) {
  1172.                     $response = $this->uploadFile($file, $subDirectory, ['image/jpeg', 'image/jpg', 'image/png']);
  1173.                     if ($response && $fileCount < 3) {
  1174.                         $surveyMedia = new SurveyMedia();
  1175.                         $surveyMedia->setOrder(null);
  1176.                         $surveyMedia->setDomain($customer->getDomain());
  1177.                         $surveyMedia->setFilename($response['filename']);
  1178.                         $surveyMedia->setDirectory('uploads/' . $subDirectory);
  1179.                         $surveyMedia->setMimeType($response['mimeType']);
  1180.                         $entityManager->persist($surveyMedia);
  1181.                         $addedSurveyMedias[] = $surveyMedia;
  1182.                         $fileCount++;
  1183.                     }
  1184.                 }
  1185.                 $entityManager->flush();
  1186.                 // Connect Survey Media to Review
  1187.                 if (!empty($addedSurveyMedias)) {
  1188.                     $centralisUser = $entityManager->getRepository(User::class)->findOneById(User::CENTRALIS_USER_ID);
  1189.                     foreach ($addedSurveyMedias as $surveyMedia) {
  1190.                         $reviewSurveyMedia = new ReviewSurveyMedia();
  1191.                         $reviewSurveyMedia->setReview($review);
  1192.                         $reviewSurveyMedia->setSurveyMedia($surveyMedia);
  1193.                         $reviewSurveyMedia->setApproved(false);
  1194.                         $reviewSurveyMedia->setCreatedBy($centralisUser);
  1195.                     }
  1196.                     $entityManager->persist($reviewSurveyMedia);
  1197.                 }
  1198.                 $entityManager->flush();
  1199.                 $this->addFlash(
  1200.                     'successReview',
  1201.                     $translator->trans('Thank you for your review. It has been submitted to the webmaster for approval')
  1202.                 );
  1203.             }
  1204.             return $form->createView();
  1205.         }
  1206.         return false;
  1207.     }
  1208.     /**
  1209.      * @param int $productId
  1210.      * @param CacheItemPoolInterface $cache
  1211.      * @param Domain $domain
  1212.      * @param Request $request
  1213.      * @param ProductHelper $productHelper
  1214.      * @return array
  1215.      * @throws \Doctrine\ORM\NoResultException
  1216.      * @throws \Doctrine\ORM\NonUniqueResultException
  1217.      */
  1218.     private function getRecommendedProducts(int $productId, CacheItemPoolInterface $cache, Domain $domain, Request $request, ProductHelper $productHelper)
  1219.     {
  1220.         $recommendedProductsCacheKey = ProductHelper::getRecommendedProductsCacheKey($domain->getId(), $request->getLocale(), $productId);
  1221.         $recommendedProductsCacheItem = $cache->getItem($recommendedProductsCacheKey);
  1222.         if (!$recommendedProductsCacheItem->isHit()) {
  1223.             $entityManager = $this->getEntityManager();
  1224.             $placeholder = $this->getImage('placeholder.png', '')->resize(Image::PRODUCT_LIST_THUMB_WIDTH, Image::PRODUCT_LIST_THUMB_HEIGHT);
  1225.             $productEntity = $entityManager->getRepository(Product::class)->findOneById($productId);
  1226.             $recommendedProducts = [];
  1227.             foreach ($productHelper->getRecommendedProducts($productEntity, $domain, 24) as $recommendedProduct) {
  1228.                 $image = $placeholder;
  1229.                 if (is_object($recommendedProduct['images'])) {
  1230.                     $image = $this->getImage($recommendedProduct['images'], 'product/' . $recommendedProduct['code'])->resize(Image::PRODUCT_LIST_THUMB_WIDTH, Image::PRODUCT_LIST_THUMB_HEIGHT);
  1231.                 }
  1232.                 $recommendedProducts[] = [
  1233.                     'id' => $recommendedProduct['id'],
  1234.                     'image' => $image,
  1235.                     'labels' => $recommendedProduct['badges'],
  1236.                     'vendor' => $recommendedProduct['vendor'],
  1237.                     'vendorId' => $recommendedProduct['vendorId'],
  1238.                     'typeId' => $recommendedProduct['productTypeId'],
  1239.                     'title' => $recommendedProduct['title'],
  1240.                     'price' => $recommendedProduct['vatPrice'],
  1241.                     'attributes' => $recommendedProduct['attributes'],
  1242.                     'available' => $recommendedProduct['availableQty'],
  1243.                     'special' => ($recommendedProduct['isDiscounted'] ? $recommendedProduct['discountVatPrice'] : false),
  1244.                     'href' => $this->url($request)->link('product', [
  1245.                         'product_id' => $recommendedProduct['id'],
  1246.                         'isBazaar'   => $recommendedProduct['isBazaar'] ?? 0
  1247.                     ]),
  1248.                     'active' => $recommendedProduct['active'],
  1249.                     'timedSalesActive' => $recommendedProduct['timedSalesActive'],
  1250.                     'reviewCount' => $recommendedProduct['reviewCount'],
  1251.                     'reviewStars' => $recommendedProduct['reviewStars'],
  1252.                     'reviews' => $recommendedProduct['reviews'],
  1253.                     'freeShipping' => $recommendedProduct['freeShipping'],
  1254.                     'warrantyYear' => $this->getWarrantyForProductType($domain->getId(), $recommendedProduct['productTypeId'])['year'],
  1255.                     'labelOS' => $this->getProductHelper($request)->getOSLabel($recommendedProduct),
  1256.                 ];
  1257.             }
  1258.             $recommendedProductsCacheItem->set($recommendedProducts);
  1259.             $recommendedProductsCacheItem->expiresAfter(self::CACHE_LIFETIME_12_HOURS);
  1260.             $cache->save($recommendedProductsCacheItem);
  1261.             return $recommendedProducts;
  1262.         } else {
  1263.             return $recommendedProductsCacheItem->get();
  1264.         }
  1265.     }
  1266.     /**
  1267.      * @param Request $request
  1268.      * @param array $filterData
  1269.      * @param Domain $domain
  1270.      */
  1271.     private function getProductListByFilter(Request $request, array $filterData, Domain $domain): array
  1272.     {
  1273.         $multiStore = $this->getMultiStoreHelper($request);
  1274.         // Default Locale
  1275.         $defaultLocale = $multiStore->getDefaultLocale();
  1276.         foreach ($filterData as $key => $value) {
  1277.             $filterData[$key] = $filterData[$key] === "" ? null : $filterData[$key];
  1278.         }
  1279.         $categoryInfo = $this->getEntityManager()->getRepository(CategoryPage::class)->findOneBy([
  1280.             'id' => $filterData['filterCategoryId'],
  1281.             'published' => true,
  1282.             'type' => CategoryPage::CATEGORY_TYPE_PRODUCT,
  1283.         ]);
  1284.         if (!$categoryInfo) {
  1285.             return [];
  1286.         }
  1287.         $categoryProductTypes = $categoryInfo->getProductTypes();
  1288.         $showWizard = false;
  1289.         if ($filterData['start'] == 0 && $categoryProductTypes->count() >= 1) {
  1290.             foreach ($categoryProductTypes as $categoryProductType) {
  1291.                 if (in_array($categoryProductType->getId(), [52, 60])) {
  1292.                     #$showWizard = true;
  1293.                     #$filterData['limit'] -= 1;
  1294.                     break;
  1295.                 }
  1296.             }
  1297.         } elseif ($filterData['start'] > 0 && $categoryProductTypes->count() >= 1) {
  1298.             $filterData['start'] -= 1;
  1299.         }
  1300.         $products = [];
  1301.         $placeholder = $this->getImage('placeholder.png', '')->resize(Image::PRODUCT_LIST_THUMB_WIDTH, Image::PRODUCT_LIST_THUMB_HEIGHT);
  1302.         $results = $this->getProductHelper($request)->getStructuredDataByFilters($filterData);
  1303.         foreach ($results as $result) {
  1304.             $image = $placeholder;
  1305.             if (is_object($result['images'])) {
  1306.                 $image = $this->getImage($result['images'], 'product/' . $result['code'])->resize(Image::PRODUCT_LIST_THUMB_WIDTH, Image::PRODUCT_LIST_THUMB_HEIGHT);
  1307.             }
  1308.             $products[] = [
  1309.                 'id'                => $result['id'],
  1310.                 'code'              => $result['code'],
  1311.                 'title'             => ProductHelper::getHeadingTitle($result, true),
  1312.                 'vendor'            => $result['vendor'],
  1313.                 'vendorId'          => $result['vendorId'],
  1314.                 'labels'            => $result['badges'],
  1315.                 'price'             => $result['vatPrice'],
  1316.                 'priceWithCoupon'   => $result['vatPriceWithCoupon'],
  1317.                 'couponCode'        => $result['couponCode'],
  1318.                 'special'           => ($result['isDiscounted'] ? $result['discountVatPrice'] : false),
  1319.                 'rawPrice'          => $result['rawPrice'],
  1320.                 'rawDiscountPrice'  => $result['rawDiscountPrice'],
  1321.                 'image'             => $image,
  1322.                 'attributes'        => $result['attributes'],
  1323.                 'attributesListTxt' => in_array($result['productTypeId'], [ProductType::PRODUCT_TYPE_ID_SMARTWATCH]) ? str_replace([' | ', 'Win 10 Pro'], [', ', 'Windows'], $result['shortDescription']) : str_replace([' | ', 'Win 10 Pro'], [', ', 'Windows'], $result['attributesListTxt']),
  1324.                 'available'         => $result['availableQty'],
  1325.                 'type'              => $result['productType'],
  1326.                 'typeId'            => $result['productTypeId'],
  1327.                 'href'              => $this->url($request)->link('product', [
  1328.                     'product_id' => $result['id'],
  1329.                     'isBazaar'   => $result['isBazaar'] ?? 0
  1330.                 ]),
  1331.                 'active'            => $result['active'],
  1332.                 'timedSalesActive'  => $result['timedSalesActive'],
  1333.                 'reviewCount'       => $result['reviewCount'],
  1334.                 'reviewStars'       => $result['reviewStars'],
  1335.                 'reviews'           => $result['reviews'],
  1336.                 'freeShipping'      => $result['freeShipping'],
  1337.                 'orderWaitingDays'  => $result['orderWaitingDays'],
  1338.                 'warrantyYear'      => $result['qualityStatusId'] == Product::QualityStatus_Bazaar ? 1 : $this->getWarrantyForProductType($domain->getId(), $result['productTypeId'])['year'],
  1339.                 'labelOS'           => $this->getProductHelper($request)->getOSLabel($result),
  1340.                 'isBestseller'      => $result['isBestseller'] ?? false
  1341.             ];
  1342.         }
  1343.         if (in_array($filterData['filterCategoryId'], [639, 640, 641]) && !empty($products)) {
  1344.             $products = array_merge([-1 => 'halloweenBanner'], $products);
  1345.         }
  1346.         if ($showWizard && !empty($products)) {
  1347.             $products = array_slice($products, 0, 2, true) +
  1348.                 [
  1349.                     'w' => 'wizardBanner',
  1350.                 ] +
  1351.                 array_slice($products, 2, count($products) - 1, true);
  1352.         }
  1353.         return $products;
  1354.     }
  1355.     /**
  1356.      * @param Request $request
  1357.      * @param array $filterData
  1358.      * @param Domain $domain
  1359.      */
  1360.     private function getNewProductListByFilter(Request $request, array $filterData, Domain $domain): array
  1361.     {
  1362.         $cache = $this->cache;
  1363.         foreach ($filterData as $key => $value) {
  1364.             $filterData[$key] = $filterData[$key] === "" ? null : $filterData[$key];
  1365.         }
  1366.         $filterDataCacheKey = md5(serialize($filterData)) . 'v2';
  1367.         $filterDataCacheItem = $cache->getItem($filterDataCacheKey);
  1368.         $products = [];
  1369.         if ($filterDataCacheItem->isHit()) {
  1370.             $products = $filterDataCacheItem->get();
  1371.         } else {
  1372.             $placeholder = $this->getImage('placeholder.png', '')->resize(Image::PRODUCT_LIST_THUMB_WIDTH, Image::PRODUCT_LIST_THUMB_HEIGHT);
  1373.             $results = $this->getProductHelper($request)->getStructuredDataByFilters($filterData);
  1374.             foreach ($results as $result) {
  1375.                 $image = $placeholder;
  1376.                 if (is_object($result['images'])) {
  1377.                     $image = $this->getImage($result['images'], 'product/' . $result['code'])->resize(Image::PRODUCT_LIST_THUMB_WIDTH, Image::PRODUCT_LIST_THUMB_HEIGHT);
  1378.                 }
  1379.                 $products[] = [
  1380.                     'id' => $result['id'],
  1381.                     'title' => ProductHelper::getHeadingTitle($result, $result['productTypeId'] == ProductType::PRODUCT_TYPE_ID_NOTEBOOK),
  1382.                     'vendor' => $result['vendor'],
  1383.                     'vendorId' => $result['vendorId'],
  1384.                     'labels' => $result['badges'],
  1385.                     'price' => $result['vatPrice'],
  1386.                     'special' => ($result['isDiscounted'] ? $result['discountVatPrice'] : false),
  1387.                     'rawPrice' => $result['rawPrice'],
  1388.                     'rawDiscountPrice' => $result['rawDiscountPrice'],
  1389.                     'image' => $image,
  1390.                     'attributes' => $result['attributes'],
  1391.                     'attributesListTxt' => $result['attributesListTxt'],
  1392.                     'available' => $result['availableQty'],
  1393.                     'type' => $result['productType'],
  1394.                     'typeId' => $result['productTypeId'],
  1395.                     'href' => $this->url($request)->link('product', [
  1396.                         'product_id'    => $result['id'], 
  1397.                         'isBazaar'      => $result['isBazaar'] ?? 0
  1398.                     ]),
  1399.                     'active' => $result['active'],
  1400.                     'timedSalesActive' => $result['timedSalesActive'],
  1401.                     'reviewCount' => $result['reviewCount'],
  1402.                     'reviewStars' => $result['reviewStars'],
  1403.                     'reviews' => $result['reviews'],
  1404.                     'freeShipping' => $result['freeShipping'],
  1405.                     'orderWaitingDays' => $result['orderWaitingDays'],
  1406.                     'warrantyYear' => $result['qualityStatusId'] == Product::QualityStatus_Bazaar ? 1 : $this->getWarrantyForProductType($domain->getId(), $result['productTypeId'])['year'],
  1407.                     'labelOS' => $this->getProductHelper($request)->getOSLabel($result), 
  1408.                     'isBestseller' => $result['isBestseller'] ?? false
  1409.                 ];
  1410.             }
  1411.             $filterDataCacheItem->set($products);
  1412.             $filterDataCacheItem->expiresAfter(self::CACHE_LIFETIME_30_MINUTES);
  1413.             $cache->save($filterDataCacheItem);
  1414.         }
  1415.         return $products;
  1416.     }
  1417.     /**
  1418.      * @Route("/category/{categoryId}", name="category_show", defaults={"_locale":""})
  1419.      * @Route("/{_locale<%supported_locales%>?}/category/{categoryId}", name="category_show_locale", defaults={"_locale":""})
  1420.      * @param int $categoryId
  1421.      * @param Request $request
  1422.      * @return Response
  1423.      * @throws \Exception
  1424.      */
  1425.     public function listAction(int $categoryId, Request $request): Response
  1426.     {
  1427.         $canRegenerateCache = $request->get('regenerate-cache') == self::REGENERATE_CACHE_TOKEN ?? false;
  1428.         $regenerateWholeSaleDomain = $canRegenerateCache && ($request->get('wholesale') ?? false);
  1429.         if ($this->getEnvironment() == 'prod') {
  1430.             \Sentry\configureScope(function (\Sentry\State\Scope $scope): void {
  1431.                 $scope->setUser([
  1432.                     'ip_address' => $_SERVER['REMOTE_ADDR'],
  1433.                 ]);
  1434.             });
  1435.         }
  1436.         // Entity Manager
  1437.         $entityManager = $this->getEntityManager();
  1438.         $data = [];
  1439.         if ($request->get('_route_params')['slug'] != null) {
  1440.             $categoryId = $entityManager->getRepository(Product::class)->checkRouteSlugForOtherCategoriesPages($request->get('_route_params')['slug'], $categoryId);
  1441.             if ($request->get('_route_params')['slug'] == 'laptop/mobil-munkaallomasok') {
  1442.                 $baseUrl = $this->getEnvironment() == 'prod' ? 'https://www.furbify.hu' : 'https://furbify.dev.hu';
  1443.                 return $this->redirect("$baseUrl/mobil-munkaallomasok", 301);
  1444.             }
  1445.         }
  1446.         $categoryInfo = $entityManager->getRepository(CategoryPage::class)->findOneBy([
  1447.             'id'        => $categoryId,
  1448.             'published' => true,
  1449.             'type'      => CategoryPage::CATEGORY_TYPE_PRODUCT,
  1450.         ]);
  1451.         $cache = $this->cache;
  1452.         // Set back to products link for cart
  1453.         $request->getSession()->set('cartBackToProductsLink', $this->url($request)->link('category', [
  1454.             'path' => $categoryId, 
  1455.             'isBazaar'  => $categoryInfo->isShowOnlyBazaar()
  1456.         ]));
  1457.         if (!$categoryInfo) {
  1458.             return $this->forward('App\AtechNet\CoreBundle\Controller\DefaultController::notFoundAction');
  1459.         }
  1460.         $multiStore = $this->getMultiStoreHelper($request);
  1461.         $currentDate = new \DateTime();
  1462.         $endDate = new \DateTime('2025-11-30');
  1463.         $startDate = new \DateTime('2025-11-07');
  1464.         $blackFridayDateIsActive = $startDate <= $currentDate && $currentDate <= $endDate;
  1465.         if ($blackFridayDateIsActive && in_array($categoryInfo->getId(), [622, 218, 621, 217, 623, 219, 624])) {
  1466.             return $this->redirect($this->url($request)->link('category_show') . '/black-friday');
  1467.         }
  1468.         // Multi-Store
  1469.         $multiStore = $this->getMultiStoreHelper($request);
  1470.         // Category Page Repository
  1471.         $categoryPageRepository = $entityManager->getRepository(CategoryPage::class);
  1472.         $categoryPageRepository->setSession($request->getSession());
  1473.         // Use Alternative Category by Language
  1474.         if ($multiStore->isLanguageSwitched()) {
  1475.             $categoryInfo = $categoryPageRepository->getAlternativeCategoryByLanguage($categoryInfo);
  1476.             if (is_null($categoryInfo)) {
  1477.                 return $this->forward('App\AtechNet\CoreBundle\Controller\DefaultController::notFoundAction', []);
  1478.             }
  1479.         }
  1480.         $translator = $this->getTranslator();
  1481.         $productHelper = $this->getProductHelper($request);
  1482.         $seoUrlHelper = $this->getSeoUrlHelper($request);
  1483.         $language = $multiStore->getLanguage();
  1484.         $defaultLanguage = $multiStore->getDefaultLanguage();
  1485.         // Different theme for bazaar category
  1486.         if ( $categoryInfo->isShowOnlyBazaar() && in_array($multiStore->getDomain()->getId(), MultiStore::getRetailDomainIDs()) ) {
  1487.             $data['isBazaar'] = true;
  1488.         } else {
  1489.             $data['isBazaar'] = false;
  1490.         }
  1491.         $data['customerTypeId'] = $request->getSession()->get('customerTypeId');
  1492.         $data['categoryId'] = $categoryId;
  1493.         $domainId = $regenerateWholeSaleDomain ? Domain::getRetailWholesaleDomainPairs()[$multiStore->getDomainId()] : $multiStore->getDomainId();
  1494.         $domain = $entityManager->getRepository(Domain::class)->findOneById($domainId);
  1495.         $parentCategoryId = $categoryInfo->getParentCategory() ? $categoryInfo->getParentCategory()->getId() : null;
  1496.         $currentParentCategorySeoUrl = $entityManager->getRepository(SeoUrl::class)->findOneBy([
  1497.             'query' => 'category_id=' . $parentCategoryId,
  1498.             'language' => $defaultLanguage,
  1499.             'archived' => false,
  1500.         ]);
  1501.         // Redirect to current parent category if archived parent called
  1502.         if (!is_null($currentParentCategorySeoUrl) && !str_contains($request->getPathInfo(), $currentParentCategorySeoUrl->getKeyWord())) {
  1503.             $seoUrl = $entityManager->getRepository(SeoUrl::class)->findOneBy([
  1504.                 'query' => 'category_id=' . $categoryId,
  1505.                 'language' => $defaultLanguage,
  1506.                 'archived' => false,
  1507.             ]);
  1508.             $filters = $request->query->all();
  1509.             if ($seoUrl) {
  1510.                 $url = $request->getSchemeAndHttpHost() . '/' . $currentParentCategorySeoUrl->getKeyWord() . '/' . $seoUrl->getKeyword();
  1511.                 if (count($filters) > 0) {
  1512.                     $filters = substr($request->getRequestUri(), strPos($request->getRequestUri(), '?'));
  1513.                     $url .= $filters;
  1514.                 }
  1515.                 return $this->redirect($url, 301);
  1516.             }
  1517.         }
  1518.         $reGenerateCache = $canRegenerateCache || $regenerateWholeSaleDomain;
  1519.         /**
  1520.          * @var PageMeta $categoryMeta
  1521.          */
  1522.         $categoryMeta = $categoryInfo->getMetaByLanguage($language);
  1523.         $showPopularProducts = $categoryInfo->isShowPopularProducts();
  1524.         $additionalSeoTitle = '';
  1525.         $indexable = $categoryInfo->isIndexable();
  1526.         if (!$categoryMeta) {
  1527.             return $this->forward('App\AtechNet\CoreBundle\Controller\DefaultController::notFoundAction');
  1528.         }
  1529.         // Filter ProductType ->
  1530.         if ($request->get('fpt') || ($request->get('sfpt') && is_numeric($request->get('sfpt')))) {
  1531.             $filterProductType = $request->get('fpt') ?? (int)$request->get('sfpt');
  1532.             $showPopularProducts = false;
  1533.             $indexable = false;
  1534.         } else {
  1535.             $filterProductType = null;
  1536.         }
  1537.         // Filter Vendor ->
  1538.         if ($request->get('fv')) {
  1539.             $filterVendor = $request->get('fv');
  1540.             $showPopularProducts = false;
  1541.             $indexable = false;
  1542.         } else {
  1543.             $filterVendor = null;
  1544.         }
  1545.         // Filter Attribute ->
  1546.         if ($request->get('fa')) {
  1547.             $filterAttribute = $request->get('fa');
  1548.             $showPopularProducts = false;
  1549.             $indexable = false;
  1550.         } else {
  1551.             $filterAttribute = null;
  1552.         }
  1553.         // Filter Price ->
  1554.         if ($request->get('fp')) {
  1555.             $currency = $domain->getCurrency();
  1556.             $filterPrice = explode('-', $request->get('fp'));
  1557.             if (!empty($filterPrice[0])) {
  1558.                 $filterPriceMin = floor((float)$filterPrice[0]);
  1559.             } else {
  1560.                 $filterPriceMin = null;
  1561.             }
  1562.             if (!empty($filterPrice[1])) {
  1563.                 $filterPriceMax = ceil((float)$filterPrice[1]);
  1564.             } else {
  1565.                 $filterPriceMax = null;
  1566.             }
  1567.             $showPopularProducts = false;
  1568.             if ($defaultLanguage->getCode() == 'sk') {
  1569.                 $additionalSeoTitle .= ', ' . $translator->trans('from') . ' ' . $filterPriceMin . ' ' . $currency . ' ' . $translator->trans('to') . ' ' . $filterPriceMax . ' ' . $currency;
  1570.             } else {
  1571.                 $additionalSeoTitle .= ', ' . $filterPriceMin . ' ' . $currency . ' - ' . $filterPriceMax . ' ' . $currency;
  1572.             }
  1573.         } else {
  1574.             $filterPriceMin = $filterPriceMax = null;
  1575.         }
  1576.         //Filter CPU mark ->
  1577.         if ($request->get('fcm')) {
  1578.             $filterCpuMark = explode('-', $request->get('fcm'));
  1579.             if (!empty($filterCpuMark[0])) {
  1580.                 $filterCpuMarkMin = (int)$filterCpuMark[0];
  1581.             } else {
  1582.                 $filterCpuMarkMin = null;
  1583.             }
  1584.             if (!empty($filterCpuMark[1])) {
  1585.                 $filterCpuMarkMax = (int)$filterCpuMark[1];
  1586.             } else {
  1587.                 $filterCpuMarkMax = null;
  1588.             }
  1589.         } else {
  1590.             $filterCpuMarkMin = $filterCpuMarkMax = null;
  1591.         }
  1592.         $data['showOnlyDiscounted'] = $categoryInfo->isShowOnlyDiscounted();
  1593.         // Filter Discounted
  1594.         if ($request->get('fd') || $categoryInfo->isShowOnlyDiscounted()) {
  1595.             $filterDiscounted = $categoryInfo->isShowOnlyDiscounted() ? 1 : (int)$request->get('fd');
  1596.             $additionalSeoTitle .= ', ' . $translator->trans('discounted products');
  1597.             $showPopularProducts = false;
  1598.         } else {
  1599.             $filterDiscounted = null;
  1600.         }
  1601.         // Filter Last Pieces ->
  1602.         if ($request->get('fl')) {
  1603.             $filterLastPieces = (int)$request->get('fl');
  1604.             $additionalSeoTitle .= ', ' . $translator->trans('last pieces');
  1605.             $showPopularProducts = false;
  1606.         } else {
  1607.             $filterLastPieces = null;
  1608.         }
  1609.         // Sort ->
  1610.         $defaultSort = 'popular';
  1611.         if ( $request->get('sort') ) {
  1612.             $sort = $request->get('sort');
  1613.             $indexable = false;
  1614.         } else {
  1615.             $sort = $defaultSort;
  1616.         }
  1617.         // Order ->
  1618.         $defaultOrder = 'desc';
  1619.         if ( $request->get('order') ) {
  1620.             $order = $request->get('order');
  1621.             $indexable = false;
  1622.         } else {
  1623.             /*if (in_array($categoryId, [460, 461, 462])) { // Cyber weekend
  1624.                 $order = 'desc';
  1625.             } else {
  1626.                 $order = 'asc';
  1627.             }*/
  1628.             $order = $defaultOrder;
  1629.         }
  1630.         // Limit ->
  1631.         $defaultLimit = 24;
  1632.         if ( $request->get('limit') ) {
  1633.             $limit = $request->get('limit');
  1634.             $indexable = false;
  1635.         } else {
  1636.             $limit = $defaultLimit;
  1637.         }
  1638.         if ($request->query->count() > 0 && $request->query->count() != 1 && !is_null($request->query->get('page'))) {
  1639.             $indexable = false;
  1640.         }
  1641.         // Page ->
  1642.         if ($request->get('page')) {
  1643.             $page = $request->get('page');
  1644.             $additionalSeoTitle .= ', ' . $page . '.' . $translator->trans('page');
  1645.         } else {
  1646.             $page = 1;
  1647.         }
  1648.         $data['breadcrumbs'] = [];
  1649.         $data['breadcrumbs'][] = $this->getBreadCrumbsBase($request);
  1650.         $parentCategoryId = 0;
  1651.         if ($categoryInfo->getParentCategory()) {
  1652.             $categoryParentMeta = $categoryInfo->getParentCategory()->getMetaByLanguage($multiStore->getLanguage());
  1653.             if ($categoryParentMeta) {
  1654.                 $data['breadcrumbs'][] = [
  1655.                     'text' => $categoryParentMeta->getTitle(),
  1656.                     'href' => $this->url($request)->link('category', [
  1657.                         'path'      => $categoryInfo->getParentCategory()->getId(), 
  1658.                         'isBazaar'  => $categoryInfo->getParentCategory()->isShowOnlyBazaar()
  1659.                     ]),
  1660.                 ];
  1661.                 $parentCategoryId = $categoryInfo->getParentCategory()->getId();
  1662.             }
  1663.         }
  1664.         $data['breadcrumbs'][] = [
  1665.             'text' => $categoryMeta->getTitle(),
  1666.             'href' => $this->url($request)->link('category', [
  1667.                 'path'      => ($parentCategoryId > 0 ? $parentCategoryId . '_' : '') . $categoryId, 
  1668.                 'isBazaar'  => $categoryInfo->isShowOnlyBazaar()
  1669.             ]),
  1670.         ];
  1671.         $data['seoTitle'] = trim($categoryMeta->getSeoTitle()) . $additionalSeoTitle;
  1672.         if (empty($data['seoTitle'])) {
  1673.             $data['seoTitle'] = $categoryMeta->getTitle();
  1674.         }
  1675.         $data['seoDescription'] = $categoryMeta->getSeoDesc() . ($additionalSeoTitle != '' ? ' ' . ucfirst(substr($additionalSeoTitle, 2)) . '.' : '');
  1676.         $data['categoryId'] = $categoryInfo->getId();
  1677.         $data['title'] = $categoryMeta->getTitle() . $additionalSeoTitle;
  1678.         $data['description'] = str_replace('&nbsp;', ' ', $categoryMeta->getContent());
  1679.         $data['socialShareImage'] = $this->getSocialShareImageHelper()->getImageUrl($categoryInfo->getSocialShareImage(), 'category');
  1680.         $data['extraSeoDesc'] = $categoryMeta->getExtraSeoDesc();
  1681.         $data['indexable'] = $indexable;
  1682.         $data['categories'] = [];
  1683.         $data['popularItems'] = [];
  1684.         $placeholder = $this->getImage('placeholder.png', '')->resize(Image::PRODUCT_CART_THUMB_WIDTH, Image::PRODUCT_CART_THUMB_HEIGHT);
  1685.         if ($showPopularProducts) {
  1686.             $popularProductsCacheKey = 'category.popular.products.c.v7.' . $domainId . '.' . $language->getCode() . '.' . $categoryInfo->getId();
  1687.             $popularProductsCacheItem = $cache->getItem($popularProductsCacheKey);
  1688.             if (!$popularProductsCacheItem->isHit() || $reGenerateCache) {
  1689.                 $popularItems = $productHelper->getPopularItemsByCategory($categoryId);
  1690.                 foreach ($popularItems as $popularItem) {
  1691.                     $image = $mobileImage = $placeholder;
  1692.                     if (is_object($popularItem['images'])) {
  1693.                         $image = $mobileImage = $this->getImage($popularItem['images'], 'product/' . $popularItem['code'])->resize(Image::PRODUCT_LIST_THUMB_WIDTH, Image::PRODUCT_LIST_THUMB_HEIGHT);
  1694.                     }
  1695.                     $shortDescription = mb_strlen($popularItem['shortDescription']) > 88 ? mb_substr($popularItem['shortDescription'], 0, 88) . '...' : $popularItem['shortDescription'];
  1696.                     $data['popularItems'][] = [
  1697.                         'id' => $popularItem['id'],
  1698.                         'image' => $image,
  1699.                         'mobileImage' => $mobileImage,
  1700.                         'vendor' => $popularItem['vendor'],
  1701.                         'title' => $popularItem['title'],
  1702.                         'description' => str_replace(' | ', ', ', $shortDescription),
  1703.                         'quantity' => $popularItem['availableQty'],
  1704.                         'price' => $popularItem['vatPrice'],
  1705.                         'special' => ($popularItem['isDiscounted'] ? $popularItem['discountVatPrice'] : false),
  1706.                         'href' => $this->url($request)->link('product', [
  1707.                             'product_id' => $popularItem['id'], 
  1708.                             'isBazaar'   => $popularItem['isBazaar'] ?? 0
  1709.                         ]),
  1710.                         'active' => $popularItem['active'],
  1711.                         'labelOS' => $this->getProductHelper($request)->getOSLabel($popularItem),
  1712.                     ];
  1713.                 }
  1714.                 $popularProductsCacheItem->set($data['popularItems']);
  1715.                 $popularProductsCacheItem->expiresAfter(self::CACHE_LIFETIME_12_HOURS);
  1716.                 $cache->save($popularProductsCacheItem);
  1717.             } else {
  1718.                 $data['popularItems'] = $popularProductsCacheItem->get();
  1719.             }
  1720.         }
  1721.         $productTypes = [];
  1722.         //sale filter change for the other category
  1723.         if (in_array($categoryInfo->getId(), CategoryPage::SALE_CATEGORY_PAGES)
  1724.             && !is_null($filterProductType)
  1725.             && $filterProductType == ProductType::PRODUCT_TYPE_ID_OTHER)
  1726.         {
  1727.             foreach ($categoryInfo->getProducts() as $product) {
  1728.                 $productType = $product->getType();
  1729.                 if (in_array($productType->getId(), ProductType::getSaleProductTypeFilterTypes())) {
  1730.                     continue;
  1731.                 }
  1732.                 if (!isset($productTypes[$productType->getId()])) {
  1733.                     $productTypes[$productType->getId()] = $productType->getId();
  1734.                 }
  1735.             }
  1736.             $filterProductType = implode(',', $productTypes);
  1737.         }
  1738.         $filterData = [
  1739.             'domainId' => $domainId,
  1740.             'filterCategoryId' => $categoryInfo->getId(),
  1741.             'filterProductType' => $filterProductType,
  1742.             'filterVendor' => $filterVendor,
  1743.             'filterAttribute' => $filterAttribute,
  1744.             'filterPriceMin' => $filterPriceMin,
  1745.             'filterPriceMax' => $filterPriceMax,
  1746.             'filterCpuMarkMin'  => $filterCpuMarkMin,
  1747.             'filterCpuMarkMax'  => $filterCpuMarkMax,
  1748.             'filterDiscounted' => $filterDiscounted,
  1749.             'filterLastPieces' => $filterLastPieces,
  1750.             'sort' => $sort,
  1751.             'order' => $order,
  1752.             'start' => ($page - 1) * $limit,
  1753.             'limit' => $limit,
  1754.             'language' => $language->getCode(),
  1755.             'cacheVer' => 3,
  1756.         ];
  1757.         $data['pagination'] = [];
  1758.         $data['categoryListLinks'] = [];
  1759.         $data['partnerLoginRedirect'] = false;
  1760.         if (!is_null($request->query->get('partner-link')) && $request->query->get('partner-link') == 1 && !$this->getLoginHelper($request)->isLoggedIn()) {
  1761.             $data['partnerLoginRedirectRoute'] = $this->generateUrl('partner_login');
  1762.             $data['partnerLoginRedirect'] = true;
  1763.         }
  1764.         $total = $this->getProductHelper($request)->getTotalByFilters($filterData);
  1765.         $arguments = [];
  1766.         $arguments['path'] = $categoryInfo->getId();
  1767.         if (!is_null($filterProductType)) {
  1768.             $arguments['fpt'] = $filterProductType;
  1769.         }
  1770.         if (!is_null($filterVendor)) {
  1771.             $arguments['fv'] = $filterVendor;
  1772.         }
  1773.         if (!is_null($filterAttribute)) {
  1774.             foreach ($filterAttribute as $key => $value) {
  1775.                 $arguments['fa[' . $key . ']'] = $value;
  1776.             }
  1777.         }
  1778.         if (!is_null($filterPriceMin) && !is_null($filterPriceMax)) {
  1779.             $arguments['fp'] = $filterPriceMin . '-' . $filterPriceMax;
  1780.         } elseif (!is_null($filterPriceMin) && is_null($filterPriceMax)) {
  1781.             $arguments['fp'] = $filterPriceMin . '-0';
  1782.         } elseif (is_null($filterPriceMin) && !is_null($filterPriceMax)) {
  1783.             $arguments['fp'] = '0-' . $filterPriceMax;
  1784.         }
  1785.         if (!is_null($filterDiscounted)) {
  1786.             $arguments['fd'] = $filterDiscounted;
  1787.         }
  1788.         if (!is_null($filterLastPieces)) {
  1789.             $arguments['fl'] = $filterLastPieces;
  1790.         }
  1791.         if ($request->get('sort')) {
  1792.             $arguments['sort'] = $sort;
  1793.         }
  1794.         if ($request->get('order')) {
  1795.             $arguments['order'] = $order;
  1796.         }
  1797.         if ($request->get('limit')) {
  1798.             $arguments['limit'] = $limit;
  1799.         }
  1800.         $arguments['page'] = '{page}';
  1801.         $data['pagination'] = [
  1802.             'total' => $total,
  1803.             'page' => $page,
  1804.             'limit' => $limit,
  1805.             'moreButton' => true,
  1806.             'url' => $this->url($request)->link('category', $arguments),
  1807.         ];
  1808.         if ($page == 1) {
  1809.             $arguments['page'] = 2;
  1810.             $data['categoryListLinks']['next'] = $this->url($request)->link('category', $arguments);
  1811.         }
  1812.         if ($page > 1) {
  1813.             if ($page == 2) {
  1814.                 unset($arguments['page']);
  1815.             } else {
  1816.                 $arguments['page'] = $page - 1;
  1817.             }
  1818.             $data['categoryListLinks']['prev'] = $this->url($request)->link('category', $arguments);
  1819.             if ($data['pagination']['total'] > 0 && $page < round($data['pagination']['total'] / $data['pagination']['limit'], PHP_ROUND_HALF_UP)) {
  1820.                 $arguments['page'] = $page + 1;
  1821.                 $data['categoryListLinks']['next'] = $this->url($request)->link('category', $arguments);
  1822.             }
  1823.         }
  1824.         // 404 Page if Page Number exceeded
  1825.         if ($page != 1 && $page > ceil($total / $limit)) {
  1826.             return $this->forward('App\AtechNet\CoreBundle\Controller\DefaultController::notFoundAction', []);
  1827.         }
  1828.         $filterDataForBuildingFilterOptions = $filterData;
  1829.         // Avoiding cache create for $filtersCacheKey in every page value change
  1830.         unset($filterDataForBuildingFilterOptions['start']);
  1831.         unset($filterDataForBuildingFilterOptions['limit']);
  1832.         unset($filterDataForBuildingFilterOptions['sort']);
  1833.         unset($filterDataForBuildingFilterOptions['order']);
  1834.         $filterDataForBuildingFilterOptionsForFilter = $filterDataForBuildingFilterOptions;
  1835.         unset($filterDataForBuildingFilterOptions['filterProductType']);
  1836.         unset($filterDataForBuildingFilterOptions['filterVendor']);
  1837.         unset($filterDataForBuildingFilterOptions['filterPriceMin']);
  1838.         unset($filterDataForBuildingFilterOptions['filterPriceMax']);
  1839.         unset($filterDataForBuildingFilterOptions['filterDiscounted']);
  1840.         unset($filterDataForBuildingFilterOptions['filterLastPieces']);
  1841.         unset($filterDataForBuildingFilterOptions['filterAttribute']);
  1842.         $filtersCacheKey = 'category.v18.' . $domainId . '.' . $language->getCode() . '.' . $categoryId . '.' . $total . md5(serialize($filterDataForBuildingFilterOptions));
  1843.         $filtersCacheItem = $cache->getItem($filtersCacheKey);
  1844.         if (!$filtersCacheItem->isHit() || $reGenerateCache) {
  1845.             $filters = $this->getProductHelper($request)->buildFilterOptions($filterDataForBuildingFilterOptionsForFilter);
  1846.             $filtersCacheItem->set($filters);
  1847.             $filtersCacheItem->expiresAfter(self::CACHE_LIFETIME_3_DAYS);
  1848.             $cache->save($filtersCacheItem);
  1849.         } else {
  1850.             $filters = $filtersCacheItem->get();
  1851.         }
  1852.         $data['filters'] = $filters;
  1853.         // For product list ajax-request
  1854.         $data['filterData'] = $filterData;
  1855.         // Filter Action
  1856.         $data['action'] = $this->url($request)->link('category', $arguments);
  1857.         $data['currency'] = $domain->getCurrency();
  1858.         $data['precision'] = $domain->getPricePrecision();
  1859.         $data['filterProductType'] = [];
  1860.         if (!is_null($filterProductType)) {
  1861.             $data['filterProductType'] = explode(',', $filterProductType);
  1862.         }
  1863.         $data['filterVendor'] = [];
  1864.         if (!is_null($filterVendor)) {
  1865.             $data['filterVendor'] = explode(',', $filterVendor);
  1866.         }
  1867.         $data['filterAttribute'] = [];
  1868.         if (!is_null($filterAttribute)) {
  1869.             foreach ($filterAttribute as $attribute) {
  1870.                 $options = explode(',', $attribute);
  1871.                 foreach ($options as $option) {
  1872.                     array_push($data['filterAttribute'], $option);
  1873.                 }
  1874.             }
  1875.         }
  1876.         if (!is_null($filterPriceMin)) {
  1877.             $data['filterPriceMin'] = $filterPriceMin;
  1878.         } else {
  1879.             $data['filterPriceMin'] = false;
  1880.         }
  1881.         if (!is_null($filterPriceMax)) {
  1882.             $data['filterPriceMax'] = $filterPriceMax;
  1883.         } else {
  1884.             $data['filterPriceMax'] = false;
  1885.         }
  1886.         if (!is_null($filterDiscounted)) {
  1887.             $data['filterDiscounted'] = $filterDiscounted;
  1888.         } else {
  1889.             $data['filterDiscounted'] = false;
  1890.         }
  1891.         if (!is_null($filterLastPieces)) {
  1892.             $data['filterLastPieces'] = $filterLastPieces;
  1893.         } else {
  1894.             $data['filterLastPieces'] = false;
  1895.         }
  1896.         // Arguments
  1897.         $arguments = [];
  1898.         $arguments['path'] = $categoryInfo->getId();
  1899.         if (!is_null($filterProductType)) {
  1900.             $arguments['fpt'] = $filterProductType;
  1901.         }
  1902.         if (!is_null($filterVendor)) {
  1903.             $arguments['fv'] = $filterVendor;
  1904.         }
  1905.         if (!is_null($filterAttribute)) {
  1906.             foreach ($filterAttribute as $key => $value) {
  1907.                 $arguments['fa[' . $key . ']'] = $value;
  1908.             }
  1909.         }
  1910.         if (!is_null($filterPriceMin) && !is_null($filterPriceMax)) {
  1911.             $arguments['fp'] = $filterPriceMin . '-' . $filterPriceMax;
  1912.         } elseif (!is_null($filterPriceMin) && is_null($filterPriceMax)) {
  1913.             $arguments['fp'] = $filterPriceMin . '-0';
  1914.         } elseif (is_null($filterPriceMin) && !is_null($filterPriceMax)) {
  1915.             $arguments['fp'] = '0-' . $filterPriceMax;
  1916.         }
  1917.         if (!is_null($filterDiscounted)) {
  1918.             $arguments['fd'] = $filterDiscounted;
  1919.         }
  1920.         if (!is_null($filterLastPieces)) {
  1921.             $arguments['fl'] = $filterLastPieces;
  1922.         }
  1923.         if ($request->get('sort')) {
  1924.             $arguments['sort'] = $sort;
  1925.         }
  1926.         if ($request->get('order')) {
  1927.             $arguments['order'] = $order;
  1928.         }
  1929.         if ($request->get('limit')) {
  1930.             $arguments['limit'] = $limit;
  1931.         }
  1932.         $data['sort'] = $sort;
  1933.         $data['order'] = $order;
  1934.         $data['limit'] = $limit;
  1935.         $data['defaultSort'] = $defaultSort;
  1936.         $data['defaultOrder'] = $defaultOrder;
  1937.         $data['defaultLimit'] = $defaultLimit;
  1938.         $data['quality_info_link'] = $this->getQualityInfoLink($domainId, $seoUrlHelper);
  1939.         $data['salesManager'] = [];
  1940.         if ($data['customerTypeId'] == MultiStore::CUSTOMER_TYPE_WHOLESALE) {
  1941.             $loggedInCustomer = $this->getLoginHelper($request)->getLoggedInCustomer();
  1942.             $salesManager = $loggedInCustomer->getSalesManager();
  1943.             if (!is_null($salesManager)) {
  1944.                 $data['salesManager']['id'] = $salesManager->getID();
  1945.                 $data['salesManager']['name'] = $salesManager->getFirstName();
  1946.                 $data['salesManager']['username'] = $salesManager->getUsername();
  1947.                 $data['salesManager']['phone'] = $salesManager->getPhone();
  1948.             }
  1949.         } else {
  1950.             $salesManager = $domain->getDefaultSalesManager();
  1951.             if (!is_null($salesManager)) {
  1952.                 $data['salesManager']['id'] = $salesManager->getID();
  1953.                 $data['salesManager']['name'] = $salesManager->getFirstName();
  1954.                 $data['salesManager']['username'] = $salesManager->getUsername();
  1955.                 $data['salesManager']['phone'] = $salesManager->getPhone();
  1956.             }
  1957.         }
  1958.         $data['domainLanguageCode'] = $domain->getLanguage()->getCode();
  1959.         if ($domain->getLanguage()->getCode() == 'hu') {
  1960.             $data['salesManager']['phone'] = $this->getContactInfos()['phone.webshop.' . $domain->getLanguage()->getCode() . '.' . $domain->getType()];
  1961.         }
  1962.         $data['webshop_phone_number'] = $this->getContactInfos()['phone.webshop.' . $domain->getLanguage()->getCode() . '.' . $domain->getType()];
  1963.         //-> Canonical Link
  1964.         if (!is_null($categoryInfo->getParentCategory())) {
  1965.             $canonicalUrl = $seoUrlHelper->link('category', [
  1966.                 'path'      => $categoryInfo->getParentCategory()->getId() . '_' . $categoryId, 
  1967.                 'isBazaar'  => $categoryInfo->isShowOnlyBazaar()
  1968.             ]);
  1969.         } else {
  1970.             $canonicalUrl = $seoUrlHelper->link('category', [
  1971.                 'path'      => $categoryId, 
  1972.                 'isBazaar'  => $categoryInfo->isShowOnlyBazaar()
  1973.             ]);
  1974.         }
  1975.         if ($canonicalUrl != $request->getUri()) {
  1976.             $data['canonical_link'] = $canonicalUrl;
  1977.         } else {
  1978.             $data['canonical_link'] = '';
  1979.         }
  1980.         //<- Canonical Link
  1981.         $data['heureka_reviews'] = '';
  1982.         if ($multiStore->getCustomerTypeId() == MultiStore::CUSTOMER_TYPE_RETAIL && in_array($domainId, [Domain::DOMAIN_ID_RT_SK, Domain::DOMAIN_ID_RT_CZ])) {
  1983.             $heureka_reviews_cache_key = 'categoryPage.heureka.reviews.V2';
  1984.             $heureka_reviews_cache_item = $cache->getItem($heureka_reviews_cache_key);
  1985.             if (!$heureka_reviews_cache_item->isHit() || $reGenerateCache) {
  1986.                 $reviews = $this->getHeurekaSiteReviews($domainId, 3);
  1987.                 $data['heureka_reviews'] = $reviews;
  1988.                 $heureka_reviews_cache_item->set($data['heureka_reviews']);
  1989.                 $heureka_reviews_cache_item->expiresAfter(self::CACHE_LIFETIME_1_DAY);
  1990.                 $cache->save($heureka_reviews_cache_item);
  1991.             } else {
  1992.                 $data['heureka_reviews'] = $heureka_reviews_cache_item->get();
  1993.             }
  1994.         }
  1995.         $flashSaleCacheKey = 'homepage.flash_sale_product.category.v1.' . $domainId . '.' . $language->getCode();
  1996.         $flashSaleCacheItem = $cache->getItem($flashSaleCacheKey);
  1997.         if ($flashSaleCacheItem->isHit()) {
  1998.             $flashSaleProduct = $flashSaleCacheItem->get();
  1999.             $active = false;
  2000.             if (!empty($flashSaleProduct) && $flashSaleProduct['timedSalesEndDate']) {
  2001.                 $saleEnd = $flashSaleProduct['timedSalesEndDate'];
  2002.                 $date = $saleEnd['month'] . ' ' . $saleEnd['day'] . ' ' . $saleEnd['year'];
  2003.                 $saleEnd['month'] = date('m', strtotime($date));
  2004.                 $active = new \DateTime() <= (new \DateTime())->setDate($saleEnd['year'], $saleEnd['month'], $saleEnd['day'])->setTime($saleEnd['hour'], 0);
  2005.             }
  2006.             $data['flashSaleProduct'] = $active ? $flashSaleProduct : [];
  2007.         } else {
  2008.             $data['flashSaleProduct'] = $this->getHiglightedFlashSaleData($request, $domain);
  2009.             $flashSaleCacheItem->set($data['flashSaleProduct']);
  2010.             $flashSaleCacheItem->expiresAfter(self::CACHE_LIFETIME_1_HOUR);
  2011.             $cache->save($flashSaleCacheItem);
  2012.         }
  2013.         $filterCacheKey = $request->query->get('fa') ?
  2014.             implode(',', $request->query->get('fa')) :
  2015.             ($request->query->get('fp') ? $request->query->get('fp') : '')
  2016.         ;
  2017.         $filterFd = (int) $request->query->get('fd');
  2018.         $filterFl = (int) $request->query->get('fl');
  2019.         $filterFa118 = (isset($request->query->get('fa')[118]) && $request->query->get('fa')[118] == 926 ? 926 : 0);
  2020.         // Header Categories
  2021.         $headerCategoriesKey = "category.header_categories.v8.$categoryId.{$filterFd}_{$filterFl}_{$filterFa118}.$domainId.{$domain->getLanguage()->getId()}.{$language->getId()}.$filterCacheKey";
  2022.         $headerCategoriesItem = $cache->getItem($headerCategoriesKey);
  2023.         if ($headerCategoriesItem->isHit()) {
  2024.             $data['header_categories'] = $headerCategoriesItem->get();
  2025.         }
  2026.         else {
  2027.             $headerCategories = [];
  2028.             if ( !in_array($categoryId, [186, 187, 197, 659, CategoryPage::UJVARI_FURDO_BANNER_SK, CategoryPage::UJVARI_FURDO_BANNER_HU, CategoryPage::UJVARI_FURDO_BANNER_CZ]) && !$categoryInfo->isShowOnlyBazaar() ) {
  2029.                 // SK
  2030.                 if ($domain->getLanguage()->getCode() == 'sk') {
  2031.                     // PC
  2032.                     if ($this->categoryHasProductType($categoryInfo, ProductType::PRODUCT_TYPE_ID_PC) || in_array($categoryId, [16, 14, 17])) {
  2033.                         $headerCategories = [
  2034.                             [
  2035.                                 'href' => $seoUrlHelper->link('category', [
  2036.                                     'path' => '4_14',
  2037.                                 ]),
  2038.                                 'title' => $translator->trans('Workstations'),
  2039.                                 'active' => $categoryId == 14,
  2040.                                 'icon' => 'workstation-pc.png',
  2041.                             ], [
  2042.                                 'href' => $seoUrlHelper->link('category', [
  2043.                                     'path' => '4_17',
  2044.                                 ]),
  2045.                                 'title' => $translator->trans('Gamer PC'),
  2046.                                 'active' => $categoryId == 17,
  2047.                                 'icon' => 'gamer-pc.png',
  2048.                             ], [
  2049.                                 'href' => $seoUrlHelper->link('category', [
  2050.                                     'path' => '4_177',
  2051.                                 ]),
  2052.                                 'title' => $translator->trans('Tiny PCs'),
  2053.                                 'active' => $categoryId == 177,
  2054.                                 'icon' => 'mini-pc.png',
  2055.                             ], [
  2056.                                 'href' => $seoUrlHelper->link('category', [
  2057.                                     'path' => '4_84',
  2058.                                 ]),
  2059.                                 'title' => $translator->trans('All in one PC'),
  2060.                                 'active' => $categoryId == 84,
  2061.                                 'icon' => 'all-in-one-pc.png',
  2062.                             ], [
  2063.                                 'href' => $seoUrlHelper->link('category', [
  2064.                                     'path' => '634',
  2065.                                 ]),
  2066.                                 'title' => $translator->trans('Windows 10 PC'),
  2067.                                 'active' => $categoryId == 634,
  2068.                                 'icon' => 'windows_10.svg',
  2069.                             ], [
  2070.                                 'href' => $seoUrlHelper->link('category', [
  2071.                                     'path' => '578',
  2072.                                 ]),
  2073.                                 'title' => $translator->trans('Windows 11 PC'),
  2074.                                 'active' => $categoryId == 578,
  2075.                                 'icon' => 'windows_11.svg',
  2076.                             ],
  2077.                         ];
  2078.                     }
  2079.                     // Notebook
  2080.                     if ($this->categoryHasProductType($categoryInfo, ProductType::PRODUCT_TYPE_ID_NOTEBOOK) || in_array($categoryId, [113, 87, 21, 241, 244, 250])) {
  2081.                         $activeState = null;
  2082.                         if ($request->query->get('fa') && isset($request->query->get('fa')[12])) {
  2083.                             $activeState = $request->query->get('fa')[12];
  2084.                         }
  2085.                         $headerCategories = [
  2086.                              [
  2087.                                 'href' => $seoUrlHelper->link('category', [
  2088.                                     'path' => '630',
  2089.                                 ]),
  2090.                                 'title' => $translator->trans('Windows 10 notebook'),
  2091.                                 'active' => $categoryId == 630,
  2092.                                 'icon' => 'windows_10.svg',
  2093.                             ], [
  2094.                                 'href' => $seoUrlHelper->link('category', [
  2095.                                     'path' => '573',
  2096.                                 ]),
  2097.                                 'title' => $translator->trans('Windows 11 notebook'),
  2098.                                 'active' => $categoryId == 573,
  2099.                                 'icon' => 'windows_11.svg',
  2100.                             ], [
  2101.                                 'href' => $seoUrlHelper->link('category', [
  2102.                                         'path' => 5,
  2103.                                     ]) . '?fa[12]=102,103,104,857,1107,1827,2064,3900,3904,3932,4011,4066,4074,4943',
  2104.                                 'title' => $translator->trans('Notebook for work'),
  2105.                                 'active' => $categoryId == 5 && $activeState == '102,103,104,857,1107,1827,2064,3900,3904,3932,4011,4066,4074,4943',
  2106.                                 'icon' => 'notebook-na-pracu.png',
  2107.                             ], [
  2108.                                 'href' => $seoUrlHelper->link('category', [
  2109.                                     'path' => '113',
  2110.                                 ]),
  2111.                                 'title' => $translator->trans('Workstation laptops'),
  2112.                                 'active' => $categoryId == 113,
  2113.                                 'icon' => 'workstation-laptop.png',
  2114.                             ],  [
  2115.                                 'href' => $seoUrlHelper->link('category', [
  2116.                                     'path' => 5,
  2117.                                     'fd' => 1,
  2118.                                 ]),
  2119.                                 'title' => $translator->trans('Discounted laptops'),
  2120.                                 'active' => $categoryId == 5 && $request->query->get('fd') == 1,
  2121.                                 'icon' => 'sale_quicklink_125x119.svg',
  2122.                             ], [
  2123.                                 'href' => $seoUrlHelper->link('category', [
  2124.                                     'path' => '7',
  2125.                                 ]),
  2126.                                 'title' => $translator->trans('Accessories'),
  2127.                                 'active' => $categoryId == 7,
  2128.                                 'icon' => 'furbify-komp-notebook-taska.jpg',
  2129.                             ],
  2130.                             /*[
  2131.                                 'href'   => $seoUrlHelper->link('category', ['path' => 5]) . '?fa[12]=196,198,251,4009,674',
  2132.                                 'title'  => $translator->trans('For free time'),
  2133.                                 'active' => $categoryId == 5 && $activeState == '196,198,251,4009,674',
  2134.                                 'icon'   => 'na-volny-cas.png'
  2135.                             ], [
  2136.                                 'href'   => $seoUrlHelper->link('category', ['path' => 5]) . '?fa[12]=4756,2111,609,1219,2183,5005,398,194,2332,2295,195',
  2137.                                 'title'  => $translator->trans('For travelling'),
  2138.                                 'active' => $categoryId == 5 && $activeState == '4756,2111,609,1219,2183,5005,398,194,2332,2295,195',
  2139.                                 'icon'   => 'travel-laptop-2.png'
  2140.                             ], [
  2141.                                 'href'   => $seoUrlHelper->link('category', ['path' => 5]) . '?fp=154-500',
  2142.                                 'title'  => $translator->trans("It doesn't cost a whole paycheck"),
  2143.                                 'active' => $categoryId == 5 && $request->query->get('fp') && $request->query->get('fp') == '154-500',
  2144.                                 'icon'   => 'notebook-do-500.svg'
  2145.                             ], [
  2146.                                 'href'   => $seoUrlHelper->link('category', ['path' => 5]) . '?fp=501-3000',
  2147.                                 'title'  => $translator->trans('Well built'),
  2148.                                 'active' => $categoryId == 5 && $request->query->get('fp') && $request->query->get('fp') == '501-3000',
  2149.                                 'icon'   => 'gold-stav.svg'
  2150.                             ], [
  2151.                                 'href'   => $seoUrlHelper->link('category', ['path' => '244']),
  2152.                                 'title'  => 'Chromebook',
  2153.                                 'active' => $categoryId == 244,
  2154.                                 'icon'   => 'chromebook.png'
  2155.                             ], [
  2156.                                 'href'   => $seoUrlHelper->link('category', ['path' => '5_43']),
  2157.                                 'title'  => $translator->trans('Laptops for seniors'),
  2158.                                 'active' => $categoryId == 43,
  2159.                                 'icon'   => 'senior-laptop.png'
  2160.                             ], [
  2161.                             'href'   => $seoUrlHelper->link('category', ['path' => '5_21']),
  2162.                             'title'  => $translator->trans('Workstation notebooks'),
  2163.                             'active' => $categoryId == 21,
  2164.                             'icon'   => 'office-laptop.png'
  2165.                             ], [
  2166.                                 'href'        => $seoUrlHelper->link('category', ['path' => '250']), // Bazar (251)
  2167.                                 'title'       => $translator->trans('Bazaar'),
  2168.                                 'active'      => $categoryId == 250,
  2169.                                 'icon'        => 'bazar-quicklink.svg',
  2170.                                 'withPadding' => TRUE
  2171.                             ]*/
  2172.                         ];
  2173.                     }
  2174.                     // Monitor
  2175.                     if ($this->categoryHasProductType($categoryInfo, ProductType::PRODUCT_TYPE_ID_MONITOR) || in_array($categoryId, [41, 39, 38])) {
  2176.                         $headerCategories = [
  2177.                             [
  2178.                                 'href' => $seoUrlHelper->link('category', [
  2179.                                     'path' => '6_41',
  2180.                                 ]),
  2181.                                 'title' => 'Dell',
  2182.                                 'active' => $categoryId == 41,
  2183.                                 'icon' => 'dell_logo_quicklink_125x119.svg',
  2184.                             ], [
  2185.                                 'href' => $seoUrlHelper->link('category', [
  2186.                                     'path' => '6_39',
  2187.                                 ]),
  2188.                                 'title' => 'Samsung',
  2189.                                 'active' => $categoryId == 39,
  2190.                                 'icon' => 'samsung_logo_quicklink_125x119.svg',
  2191.                             ], [
  2192.                                 'href' => $seoUrlHelper->link('category', [
  2193.                                     'path' => '6_38',
  2194.                                 ]),
  2195.                                 'title' => 'HP',
  2196.                                 'active' => $categoryId == 38,
  2197.                                 'icon' => 'hp_logo_quicklink_125x119.svg',
  2198.                             ], [
  2199.                                 'href' => $seoUrlHelper->link('category', [
  2200.                                     'path' => 6,
  2201.                                 ]) . '?fv=47',
  2202.                                 'title' => 'Philips',
  2203.                                 'active' => $categoryId == 6 && $request->query->get('fv') && $request->query->get('fv') == 47,
  2204.                                 'icon' => 'philips_logo_quicklink_125x119.svg',
  2205.                             ], [
  2206.                                 'href' => $seoUrlHelper->link('category', [
  2207.                                     'path' => 6,
  2208.                                 ]) . '?fv=32',
  2209.                                 'title' => 'Lenovo',
  2210.                                 'active' => $categoryId == 6 && $request->query->get('fv') && $request->query->get('fv') == 32,
  2211.                                 'icon' => 'lenovo_logo_quicklink_125x119.svg',
  2212.                             ], [
  2213.                                 'href' => $seoUrlHelper->link('category', [
  2214.                                     'path' => 6,
  2215.                                 ]) . '?fa[63]=632',
  2216.                                 'title' => 'Full HD',
  2217.                                 'active' => $categoryId == 6 && isset($request->query->get('fa')[63]) && $request->query->get('fa')[63] == 632,
  2218.                                 'icon' => 'full_hd_quicklink_125x119.svg',
  2219.                             ], [
  2220.                                 'href' => $seoUrlHelper->link('category', [
  2221.                                     'path' => 6,
  2222.                                 ]) . '?fa[118]=926',
  2223.                                 'title' => 'IPS panel',
  2224.                                 'active' => $categoryId == 6 && isset($request->query->get('fa')[118]) && $request->query->get('fa')[118] == 926,
  2225.                                 'icon' => 'ipslogo_quicklink_125x119.svg',
  2226.                             ], /*[
  2227.                                 'href' => $seoUrlHelper->link('category', [
  2228.                                     'path' => '378',
  2229.                                 ]),
  2230.                                 'title' => $translator->trans('Bazaar'),
  2231.                                 'active' => $categoryId == 378,
  2232.                                 'icon' => 'bazar-quicklink.svg',
  2233.                                 'withPadding' => true,
  2234.                             ],*/ [
  2235.                                 'href' => $seoUrlHelper->link('category', [
  2236.                                     'path' => 6,
  2237.                                     'fd' => 1,
  2238.                                 ]),
  2239.                                 'title' => $translator->trans('Discounted monitors'),
  2240.                                 'active' => $categoryId == 6 && $request->query->get('fd') == 1,
  2241.                                 'icon' => 'sale_quicklink_125x119.svg',
  2242.                             ], [
  2243.                                 'href' => $seoUrlHelper->link('category', [
  2244.                                     'path' => 581,
  2245.                                 ]),
  2246.                                 'title' => $translator->trans('Touch monitors'), // 'Dotykové monitory',
  2247.                                 'active' => $categoryId == 581,
  2248.                                 'icon' => 'monitor_touchscreen.svg',
  2249.                             ],
  2250.                         ];
  2251.                     }
  2252.                 }
  2253.                 // HU
  2254.                 if ($domain->getLanguage()->getCode() == 'hu') {
  2255.                     // PC
  2256.                     if ($this->categoryHasProductType($categoryInfo, ProductType::PRODUCT_TYPE_ID_PC) || in_array($categoryId, [54, 52, 55])) {
  2257.                         $headerCategories = [
  2258.                             [
  2259.                                 'href' => $seoUrlHelper->link('category', [
  2260.                                     'path' => '48_52',
  2261.                                 ]),
  2262.                                 'title' => $translator->trans('Workstations'),
  2263.                                 'active' => $categoryId == 52,
  2264.                                 'icon' => 'workstation-pc.png',
  2265.                             ], [
  2266.                                 'href' => $seoUrlHelper->link('category', [
  2267.                                     'path' => '48_55',
  2268.                                 ]),
  2269.                                 'title' => $translator->trans('Gamer PC'),
  2270.                                 'active' => $categoryId == 55,
  2271.                                 'icon' => 'gamer-pc.png',
  2272.                             ], [
  2273.                                 'href' => $seoUrlHelper->link('category', [
  2274.                                     'path' => '48_178',
  2275.                                 ]),
  2276.                                 'title' => $translator->trans('Tiny PCs'),
  2277.                                 'active' => $categoryId == 178,
  2278.                                 'icon' => 'mini-pc.png',
  2279.                             ], [
  2280.                                 'href' => $seoUrlHelper->link('category', [
  2281.                                     'path' => '48_85',
  2282.                                 ]),
  2283.                                 'title' => $translator->trans('All in one PC'),
  2284.                                 'active' => $categoryId == 85,
  2285.                                 'icon' => 'all-in-one-pc.png',
  2286.                             ], [
  2287.                                 'href' => $seoUrlHelper->link('category', [
  2288.                                     'path' => '635',
  2289.                                 ]),
  2290.                                 'title' => $translator->trans('Windows 10 PC'),
  2291.                                 'active' => $categoryId == 635,
  2292.                                 'icon' => 'windows_10.svg',
  2293.                             ],  [
  2294.                                 'href' => $seoUrlHelper->link('category', [
  2295.                                     'path' => '577',
  2296.                                 ]),
  2297.                                 'title' => $translator->trans('Windows 11 PC'),
  2298.                                 'active' => $categoryId == 577,
  2299.                                 'icon' => 'windows_11.svg',
  2300.                             ],
  2301.                         ];
  2302.                     }
  2303.                     // Notebook
  2304.                     if ($this->categoryHasProductType($categoryInfo, ProductType::PRODUCT_TYPE_ID_NOTEBOOK) || in_array($categoryId, [112, 88, 60, 61, 240, 243, 249])) {
  2305.                         $headerCategories = [
  2306.                             [
  2307.                                 'href' => $seoUrlHelper->link('category', [
  2308.                                     'path' => '631',
  2309.                                 ]),
  2310.                                 'title' => $translator->trans('Windows 10 notebook'),
  2311.                                 'active' => $categoryId == 631,
  2312.                                 'icon' => 'windows_10.svg',
  2313.                             ], [
  2314.                                 'href' => $seoUrlHelper->link('category', [
  2315.                                     'path' => '574',
  2316.                                 ]),
  2317.                                 'title' => $translator->trans('Windows 11 notebook'),
  2318.                                 'active' => $categoryId == 574,
  2319.                                 'icon' => 'windows_11.svg',
  2320.                             ],[
  2321.                                 'href' => $seoUrlHelper->link('category', [
  2322.                                     'path' => '56_60',
  2323.                                 ]),
  2324.                                 'title' => $translator->trans('Work laptops'),
  2325.                                 'active' => $categoryId == 60,
  2326.                                 'icon' => 'office-laptop.png',
  2327.                             ], [
  2328.                                 'href' => $seoUrlHelper->link('category', [
  2329.                                     'path' => '112',
  2330.                                 ]),
  2331.                                 'title' => $translator->trans('Workstation laptop'),
  2332.                                 'active' => $categoryId == 112,
  2333.                                 'icon' => 'workstation-laptop.png',
  2334.                             ], [
  2335.                                 'href' => $seoUrlHelper->link('category', [
  2336.                                     'path' => 56,
  2337.                                     'fd' => 1,
  2338.                                 ]),
  2339.                                 'title' => $translator->trans('Discounted notebooks'),
  2340.                                 'active' => $categoryId == 56 && $request->query->get('fd') == 1,
  2341.                                 'icon' => 'sale_quicklink_125x119.svg',
  2342.                             ],  [
  2343.                                 'href' => $seoUrlHelper->link('category', [
  2344.                                     'path' => '567',
  2345.                                 ]),
  2346.                                 'title' => $translator->trans('Accessories'),
  2347.                                 'active' => $categoryId == 567,
  2348.                                 'icon' => 'furbify-komp-notebook-taska.jpg',
  2349.                             ],
  2350.                             /*  [
  2351.                                 'href'   => $seoUrlHelper->link('category', ['path' => '243']),
  2352.                                 'title'  => 'Chromebook',
  2353.                                 'active' => $categoryId == 243,
  2354.                                 'icon'   => 'chromebook.png'
  2355.                             ], [
  2356.                                 'href'   => $seoUrlHelper->link('category', ['path' => '56_76']),
  2357.                                 'title'  => $translator->trans('Laptops for seniors'),
  2358.                                 'active' => $categoryId == 76,
  2359.                                 'icon'   => 'senior-laptop.png'
  2360.                             ], [
  2361.                                 'href'        => $seoUrlHelper->link('category', ['path' => '249']),
  2362.                                 'title'       => $translator->trans('Bazaar') . ' / szépséghibás',
  2363.                                 'active'      => $categoryId == 249,
  2364.                                 'icon'        => 'bazar-quicklink.svg',
  2365.                                 'withPadding' => TRUE
  2366.                             ]*/
  2367.                         ];
  2368.                     }
  2369.                     // Monitor
  2370.                     if ($this->categoryHasProductType($categoryInfo, ProductType::PRODUCT_TYPE_ID_MONITOR) || in_array($categoryId, [75, 80, 79])) {
  2371.                         $headerCategories = [
  2372.                             [
  2373.                                 'href' => $seoUrlHelper->link('category', [
  2374.                                     'path' => '78_75',
  2375.                                 ]),
  2376.                                 'title' => 'Dell',
  2377.                                 'active' => $categoryId == 75,
  2378.                                 'icon' => 'dell_logo_quicklink_125x119.svg',
  2379.                             ], [
  2380.                                 'href' => $seoUrlHelper->link('category', [
  2381.                                     'path' => '78_80',
  2382.                                 ]),
  2383.                                 'title' => 'Samsung',
  2384.                                 'active' => $categoryId == 80,
  2385.                                 'icon' => 'samsung_logo_quicklink_125x119.svg',
  2386.                             ], [
  2387.                                 'href' => $seoUrlHelper->link('category', [
  2388.                                     'path' => '78_79',
  2389.                                 ]),
  2390.                                 'title' => 'HP',
  2391.                                 'active' => $categoryId == 79,
  2392.                                 'icon' => 'hp_logo_quicklink_125x119.svg',
  2393.                             ], [
  2394.                                 'href' => $seoUrlHelper->link('category', [
  2395.                                     'path' => 78,
  2396.                                 ]) . '?fv=47',
  2397.                                 'title' => 'Philips',
  2398.                                 'active' => $categoryId == 78 && $request->query->get('fv') && $request->query->get('fv') == 47,
  2399.                                 'icon' => 'philips_logo_quicklink_125x119.svg',
  2400.                             ], [
  2401.                                 'href' => $seoUrlHelper->link('category', [
  2402.                                     'path' => 78,
  2403.                                 ]) . '?fv=32',
  2404.                                 'title' => 'Lenovo',
  2405.                                 'active' => $categoryId == 78 && $request->query->get('fv') && $request->query->get('fv') == 32,
  2406.                                 'icon' => 'lenovo_logo_quicklink_125x119.svg',
  2407.                             ], [
  2408.                                 'href' => $seoUrlHelper->link('category', [
  2409.                                     'path' => 78,
  2410.                                 ]) . '?fa[63]=632',
  2411.                                 'title' => 'Full HD',
  2412.                                 'active' => $categoryId == 78 && isset($request->query->get('fa')[63]) && $request->query->get('fa')[63] == 632,
  2413.                                 'icon' => 'full_hd_quicklink_125x119.svg',
  2414.                             ], [
  2415.                                 'href' => $seoUrlHelper->link('category', [
  2416.                                     'path' => 78,
  2417.                                 ]) . '?fa[118]=926',
  2418.                                 'title' => 'IPS panel',
  2419.                                 'active' => $categoryId == 78 && isset($request->query->get('fa')[118]) && $request->query->get('fa')[118] == 926,
  2420.                                 'icon' => 'ipslogo_quicklink_125x119.svg',
  2421.                             ], /*[
  2422.                                 'href' => $seoUrlHelper->link('category', [
  2423.                                     'path' => '377',
  2424.                                 ]),
  2425.                                 'title' => $translator->trans('Bazaar'),
  2426.                                 'active' => $categoryId == 377,
  2427.                                 'icon' => 'bazar-quicklink.svg',
  2428.                                 'withPadding' => true,
  2429.                             ],*/ [
  2430.                                 'href' => $seoUrlHelper->link('category', [
  2431.                                     'path' => 78,
  2432.                                     'fd' => 1,
  2433.                                 ]),
  2434.                                 'title' => $translator->trans('Discounted monitors'),
  2435.                                 'active' => $categoryId == 78 && $request->query->get('fd') == 1,
  2436.                                 'icon' => 'sale_quicklink_125x119.svg',
  2437.                             ], [
  2438.                                 'href' => $seoUrlHelper->link('category', [
  2439.                                     'path' => 580,
  2440.                                 ]),
  2441.                                 'title' => 'Érintőképernyős monitor',
  2442.                                 'active' => $categoryId == 580,
  2443.                                 'icon' => 'monitor_touchscreen.svg',
  2444.                             ],
  2445.                         ];
  2446.                     }
  2447.                 }
  2448.                 // CZ
  2449.                 if ($domain->getLanguage()->getCode() == 'cz') {
  2450.                     // PC
  2451.                     if ($this->categoryHasProductType($categoryInfo, ProductType::PRODUCT_TYPE_ID_PC) || in_array($categoryId, [128, 126, 129])) {
  2452.                         $headerCategories = [
  2453.                             [
  2454.                                 'href' => $seoUrlHelper->link('category', [
  2455.                                     'path' => '122_126',
  2456.                                 ]),
  2457.                                 'title' => $translator->trans('Workstations'),
  2458.                                 'active' => $categoryId == 126,
  2459.                                 'icon' => 'workstation-pc.png',
  2460.                             ], [
  2461.                                 'href' => $seoUrlHelper->link('category', [
  2462.                                     'path' => '122_129',
  2463.                                 ]),
  2464.                                 'title' => $translator->trans('Gamer PC'),
  2465.                                 'active' => $categoryId == 129,
  2466.                                 'icon' => 'gamer-pc.png',
  2467.                             ], [
  2468.                                 'href' => $seoUrlHelper->link('category', [
  2469.                                     'path' => '122_179',
  2470.                                 ]),
  2471.                                 'title' => $translator->trans('Tiny PCs'),
  2472.                                 'active' => $categoryId == 179,
  2473.                                 'icon' => 'mini-pc.png',
  2474.                             ], [
  2475.                                 'href' => $seoUrlHelper->link('category', [
  2476.                                     'path' => '122_155',
  2477.                                 ]),
  2478.                                 'title' => $translator->trans('All in one PC'),
  2479.                                 'active' => $categoryId == 155,
  2480.                                 'icon' => 'all-in-one-pc.png',
  2481.                             ], [
  2482.                                 'href' => $seoUrlHelper->link('category', [
  2483.                                     'path' => '636',
  2484.                                 ]),
  2485.                                 'title' => $translator->trans('Windows 10 PC'),
  2486.                                 'active' => $categoryId == 636,
  2487.                                 'icon' => 'windows_11.svg',
  2488.                             ], [
  2489.                                 'href' => $seoUrlHelper->link('category', [
  2490.                                     'path' => '579',
  2491.                                 ]),
  2492.                                 'title' => $translator->trans('Windows 11 PC'),
  2493.                                 'active' => $categoryId == 579,
  2494.                                 'icon' => 'windows_11.svg',
  2495.                             ],
  2496.                         ];
  2497.                     }
  2498.                     // Notebook
  2499.                     if ($this->categoryHasProductType($categoryInfo, ProductType::PRODUCT_TYPE_ID_NOTEBOOK) || in_array($categoryId, [175, 157, 134, 242, 245, 251])) {
  2500.                         $headerCategories = [
  2501.                             [
  2502.                                 'href' => $seoUrlHelper->link('category', [
  2503.                                     'path' => '632',
  2504.                                 ]),
  2505.                                 'title' => $translator->trans('Windows 10 notebook'),
  2506.                                 'active' => $categoryId == 630,
  2507.                                 'icon' => 'windows_10.svg',
  2508.                             ], [
  2509.                                 'href' => $seoUrlHelper->link('category', [
  2510.                                     'path' => '575',
  2511.                                 ]),
  2512.                                 'title' => $translator->trans('Windows 11 notebook'),
  2513.                                 'active' => $categoryId == 575,
  2514.                                 'icon' => 'windows_11.svg',
  2515.                             ], [
  2516.                                 'href' => $seoUrlHelper->link('category', [
  2517.                                     'path' => '130_134',
  2518.                                 ]),
  2519.                                 'title' => $translator->trans('Workstation notebooks'),
  2520.                                 'active' => $categoryId == 134,
  2521.                                 'icon' => 'office-laptop.png',
  2522.                             ], [
  2523.                                 'href' => $seoUrlHelper->link('category', [
  2524.                                     'path' => '130_175',
  2525.                                 ]),
  2526.                                 'title' => $translator->trans('Workstation laptops'),
  2527.                                 'active' => $categoryId == 175,
  2528.                                 'icon' => 'workstation-laptop.png',
  2529.                             ], [
  2530.                                 'href' => $seoUrlHelper->link('category', [
  2531.                                     'path' => 130,
  2532.                                     'fd' => 1,
  2533.                                 ]),
  2534.                                 'title' => $translator->trans('Discounted laptops'),
  2535.                                 'active' => $categoryId == 130 && $request->query->get('fd') == 1,
  2536.                                 'icon' => 'sale_quicklink_125x119.svg',
  2537.                                 'withPadding' => true,
  2538.                             ],  [
  2539.                                 'href' => $seoUrlHelper->link('category', [
  2540.                                     'path' => '118',
  2541.                                 ]),
  2542.                                 'title' => $translator->trans('Accessories'),
  2543.                                 'active' => $categoryId == 118,
  2544.                                 'icon' => 'furbify-komp-notebook-taska.jpg',
  2545.                             ],
  2546.                             /*  [
  2547.                                 'href'   => $seoUrlHelper->link('category', ['path' => '130_245']),
  2548.                                 'title'  => 'Chromebook',
  2549.                                 'active' => $categoryId == 245,
  2550.                                 'icon'   => 'chromebook.png'
  2551.                             ], [
  2552.                                 'href'   => $seoUrlHelper->link('category', ['path' => '130_154']),
  2553.                                 'title'  => $translator->trans('Laptops for seniors'),
  2554.                                 'active' => $categoryId == 154,
  2555.                                 'icon'   => 'senior-laptop.png'
  2556.                             ], [
  2557.                                 'href'   => $seoUrlHelper->link('category', ['path' => '130_251']),
  2558.                                 'title'  => $translator->trans('Bazaar'),
  2559.                                 'active' => $categoryId == 251,
  2560.                                 'icon'   => 'bazar-quicklink.svg'
  2561.                             ]*/
  2562.                         ];
  2563.                     }
  2564.                     // Monitor
  2565.                     if ($this->categoryHasProductType($categoryInfo, ProductType::PRODUCT_TYPE_ID_MONITOR) || in_array($categoryId, [153, 151, 150])) {
  2566.                         $headerCategories = [
  2567.                             [
  2568.                                 'href' => $seoUrlHelper->link('category', [
  2569.                                     'path' => '149_153',
  2570.                                 ]),
  2571.                                 'title' => 'Dell',
  2572.                                 'active' => $categoryId == 153,
  2573.                                 'icon' => 'dell_logo_quicklink_125x119.svg',
  2574.                             ], [
  2575.                                 'href' => $seoUrlHelper->link('category', [
  2576.                                     'path' => '149_151',
  2577.                                 ]),
  2578.                                 'title' => 'Samsung',
  2579.                                 'active' => $categoryId == 151,
  2580.                                 'icon' => 'samsung_logo_quicklink_125x119.svg',
  2581.                             ], [
  2582.                                 'href' => $seoUrlHelper->link('category', [
  2583.                                     'path' => '149_150',
  2584.                                 ]),
  2585.                                 'title' => 'HP',
  2586.                                 'active' => $categoryId == 150,
  2587.                                 'icon' => 'hp_logo_quicklink_125x119.svg',
  2588.                             ], [
  2589.                                 'href' => $seoUrlHelper->link('category', [
  2590.                                     'path' => 149,
  2591.                                 ]) . '?fv=47',
  2592.                                 'title' => 'Philips',
  2593.                                 'active' => $categoryId == 149 && $request->query->get('fv') && $request->query->get('fv') == 47,
  2594.                                 'icon' => 'philips_logo_quicklink_125x119.svg',
  2595.                             ], [
  2596.                                 'href' => $seoUrlHelper->link('category', [
  2597.                                     'path' => 149,
  2598.                                 ]) . '?fv=32',
  2599.                                 'title' => 'Lenovo',
  2600.                                 'active' => $categoryId == 149 && $request->query->get('fv') && $request->query->get('fv') == 32,
  2601.                                 'icon' => 'lenovo_logo_quicklink_125x119.svg',
  2602.                             ], [
  2603.                                 'href' => $seoUrlHelper->link('category', [
  2604.                                     'path' => 149,
  2605.                                 ]) . '?fa[63]=632',
  2606.                                 'title' => 'Full HD',
  2607.                                 'active' => $categoryId == 149 && isset($request->query->get('fa')[63]) && $request->query->get('fa')[63] == 632,
  2608.                                 'icon' => 'full_hd_quicklink_125x119.svg',
  2609.                             ], [
  2610.                                 'href' => $seoUrlHelper->link('category', [
  2611.                                     'path' => 149,
  2612.                                 ]) . '?fa[118]=926',
  2613.                                 'title' => 'IPS panel',
  2614.                                 'active' => $categoryId == 149 && isset($request->query->get('fa')[118]) && $request->query->get('fa')[118] == 926,
  2615.                                 'icon' => 'ipslogo_quicklink_125x119.svg',
  2616.                             ], /*[
  2617.                                 'href' => $seoUrlHelper->link('category', [
  2618.                                     'path' => '379',
  2619.                                 ]),
  2620.                                 'title' => $translator->trans('Bazaar'),
  2621.                                 'active' => $categoryId == 379,
  2622.                                 'icon' => 'bazar-quicklink.svg',
  2623.                                 'withPadding' => true,
  2624.                             ],*/ [
  2625.                                 'href' => $seoUrlHelper->link('category', [
  2626.                                     'path' => 149,
  2627.                                     'fd' => 1,
  2628.                                 ]),
  2629.                                 'title' => $translator->trans('Discounted monitors'),
  2630.                                 'active' => $categoryId == 149 && $request->query->get('fd') == 1,
  2631.                                 'icon' => 'sale_quicklink_125x119.svg',
  2632.                             ], [
  2633.                                 'href' => $seoUrlHelper->link('category', [
  2634.                                     'path' => 582,
  2635.                                 ]),
  2636.                                 'title' => 'Dotykové monitory',
  2637.                                 'active' => $categoryId == 582,
  2638.                                 'icon' => 'monitor_touchscreen.svg',
  2639.                             ],
  2640.                         ];
  2641.                     }
  2642.                 }
  2643.                 if ($domain->getLanguage()->getCode() == 'en') {
  2644.                     // PC
  2645.                     if ($this->categoryHasProductType($categoryInfo, 60) || in_array($categoryId, [54, 52, 55])) {
  2646.                         $headerCategories = [
  2647.                             [
  2648.                                 'href' => $seoUrlHelper->link('category', [
  2649.                                     'path' => '281',
  2650.                                 ]),
  2651.                                 'title' => 'Workstation PC',
  2652.                                 'active' => $categoryId == 281,
  2653.                                 'icon' => 'workstation-pc.png',
  2654.                             ], [
  2655.                                 'href' => $seoUrlHelper->link('category', [
  2656.                                     'path' => '284',
  2657.                                 ]),
  2658.                                 'title' => 'Gaming PC',
  2659.                                 'active' => $categoryId == 284,
  2660.                                 'icon' => 'gamer-pc.png',
  2661.                             ], [
  2662.                                 'href' => $seoUrlHelper->link('category', [
  2663.                                     'path' => '323',
  2664.                                 ]),
  2665.                                 'title' => 'Mini PC',
  2666.                                 'active' => $categoryId == 323,
  2667.                                 'icon' => 'mini-pc.png',
  2668.                             ], [
  2669.                                 'href' => $seoUrlHelper->link('category', [
  2670.                                     'path' => '310',
  2671.                                 ]),
  2672.                                 'title' => 'All In One PC',
  2673.                                 'active' => $categoryId == 310,
  2674.                                 'icon' => 'komplet-pc.png',
  2675.                             ], [
  2676.                                 'href' => $seoUrlHelper->link('category', [
  2677.                                     'path' => '637',
  2678.                                 ]),
  2679.                                 'title' => $translator->trans('Windows 10 PC'),
  2680.                                 'active' => $categoryId == 637,
  2681.                                 'icon' => 'windows_11.svg',
  2682.                             ], [
  2683.                                 'href' => $seoUrlHelper->link('category', [
  2684.                                     'path' => '638',
  2685.                                 ]),
  2686.                                 'title' => $translator->trans('Windows 11 PC'),
  2687.                                 'active' => $categoryId == 638,
  2688.                                 'icon' => 'windows_11.svg',
  2689.                             ],
  2690.                         ];
  2691.                     }
  2692.                     // Notebook
  2693.                     if ($this->categoryHasProductType($categoryInfo, 52) || in_array($categoryId, [112, 88, 60, 61, 240, 243, 249])) {
  2694.                         $headerCategories = [
  2695.                             [
  2696.                                 'href' => $seoUrlHelper->link('category', [
  2697.                                     'path' => '633',
  2698.                                 ]),
  2699.                                 'title' => $translator->trans('Windows 10 notebook'),
  2700.                                 'active' => $categoryId == 633,
  2701.                                 'icon' => 'windows_10.svg',
  2702.                             ], [
  2703.                                 'href' => $seoUrlHelper->link('category', [
  2704.                                     'path' => '576',
  2705.                                 ]),
  2706.                                 'title' => $translator->trans('Windows 11 notebook'),
  2707.                                 'active' => $categoryId == 576,
  2708.                                 'icon' => 'windows_11.svg',
  2709.                             ], [
  2710.                                 'href' => $seoUrlHelper->link('category', [
  2711.                                     'path' => '346',
  2712.                                 ]),
  2713.                                 'title' => 'Workstation laptop',
  2714.                                 'active' => $categoryId == 346,
  2715.                                 'icon' => 'workstation-laptop.png',
  2716.                             ], [
  2717.                                 'href' => $seoUrlHelper->link('category', [
  2718.                                     'path' => '291',
  2719.                                 ]),
  2720.                                 'title' => 'Gaming laptop',
  2721.                                 'active' => $categoryId == 291,
  2722.                                 'icon' => 'gamer-laptop.png',
  2723.                             ], [
  2724.                                 'href' => $seoUrlHelper->link('category', [
  2725.                                     'path' => 285,
  2726.                                     'fd' => 1,
  2727.                                 ]),
  2728.                                 'title' => 'Laptop Sale',
  2729.                                 'active' => $categoryId == 285 && $request->query->get('fd') == 1,
  2730.                                 'icon' => 'sale_quicklink_125x119.svg',
  2731.                             ], [
  2732.                                 'href'   => $seoUrlHelper->link('category', [
  2733.                                     'path' => '273',
  2734.                                 ]),
  2735.                                 'title'  => $translator->trans('Accessories'),
  2736.                                 'active' => $categoryId == 273,
  2737.                                 'icon'   => 'furbify-komp-notebook-taska.jpg',
  2738.                             ],
  2739.                         ];
  2740.                     }
  2741.                     if ($this->categoryHasProductType($categoryInfo, 44) || in_array($categoryId, [75, 80, 79])) { // Monitor
  2742.                         $headerCategories = [
  2743.                             [
  2744.                                 'href' => $seoUrlHelper->link('category', [
  2745.                                     'path' => '488',
  2746.                                 ]),
  2747.                                 'title' => 'Samsung',
  2748.                                 'active' => $categoryId == 488,
  2749.                                 'icon' => 'samsung_logo_quicklink_125x119.svg',
  2750.                             ], [
  2751.                                 'href' => $seoUrlHelper->link('category', [
  2752.                                     'path' => '490',
  2753.                                 ]),
  2754.                                 'title' => 'Dell',
  2755.                                 'active' => $categoryId == 490,
  2756.                                 'icon' => 'dell_logo_quicklink_125x119.svg',
  2757.                             ], [
  2758.                                 'href' => $seoUrlHelper->link('category', [
  2759.                                     'path' => '487',
  2760.                                 ]),
  2761.                                 'title' => 'HP',
  2762.                                 'active' => $categoryId == 487,
  2763.                                 'icon' => 'hp_logo_quicklink_125x119.svg',
  2764.                             ], [
  2765.                                 'href' => $seoUrlHelper->link('category', [
  2766.                                     'path' => 304,
  2767.                                 ]) . '?fv=47',
  2768.                                 'title' => 'Philips',
  2769.                                 'active' => $categoryId == 304 && $request->query->get('fv') && $request->query->get('fv') == 47,
  2770.                                 'icon' => 'philips_logo_quicklink_125x119.svg',
  2771.                             ], [
  2772.                                 'href' => $seoUrlHelper->link('category', [
  2773.                                     'path' => 304,
  2774.                                 ]) . '?fv=32',
  2775.                                 'title' => 'Lenovo',
  2776.                                 'active' => $categoryId == 304 && $request->query->get('fv') && $request->query->get('fv') == 32,
  2777.                                 'icon' => 'lenovo_logo_quicklink_125x119.svg',
  2778.                             ], [
  2779.                                 'href' => $seoUrlHelper->link('category', [
  2780.                                     'path' => 304,
  2781.                                 ]) . '?fa[63]=632',
  2782.                                 'title' => 'Monitor Sale',
  2783.                                 'active' => $categoryId == 304 && isset($request->query->get('fa')[63]) && $request->query->get('fa')[63] == 632,
  2784.                                 'icon' => 'sale_quicklink_125x119.svg',
  2785.                             ],
  2786.                         ];
  2787.                     }
  2788.                 }
  2789.             }
  2790.             $data['header_categories'] = $headerCategories;
  2791.             $headerCategoriesItem->set($data['header_categories']);
  2792.             $headerCategoriesItem->expiresAfter(self::CACHE_LIFETIME_7_DAYS);
  2793.             $cache->save($headerCategoriesItem);
  2794.         }
  2795.         if (in_array($categoryId, CategoryPage::SALE_CATEGORY_PAGES)) {
  2796.             $headerProductTypesKey = "category.header_product_types.{$categoryId}.{$domain->getId()}";
  2797.             $headerProductTypesItem = $cache->getItem($headerProductTypesKey);
  2798.             $salesSelectedProductType = null;
  2799.             if ($request->query->has('sfpt') && is_numeric($request->get('sfpt'))) {
  2800.                 $salesSelectedProductType = $request->query->get('sfpt');
  2801.             }
  2802.             $productTypes = [
  2803.                 ProductType::PRODUCT_TYPE_ID_NOTEBOOK   => [
  2804.                     'href'   => '?sfpt=' . ProductType::PRODUCT_TYPE_ID_NOTEBOOK,
  2805.                     'title'  => $translator->trans('Notebooks'),
  2806.                     'active' => $salesSelectedProductType == ProductType::PRODUCT_TYPE_ID_NOTEBOOK,
  2807.                     'icon'   => 'theme/images/category/laptop-200x150.png',
  2808.                 ],
  2809.                 ProductType::PRODUCT_TYPE_ID_PC         => [
  2810.                     'href'   => '?sfpt=' . ProductType::PRODUCT_TYPE_ID_PC,
  2811.                     'title'  => $translator->trans('Desktop PC'),
  2812.                     'active' => $salesSelectedProductType == ProductType::PRODUCT_TYPE_ID_PC,
  2813.                     'icon'   => '/theme/images/category/pc-set-200x150.png',
  2814.                 ],
  2815.                 ProductType::PRODUCT_TYPE_ID_MONITOR    => [
  2816.                     'href'   => '?sfpt=' . ProductType::PRODUCT_TYPE_ID_MONITOR,
  2817.                     'title'  => $translator->trans('Monitors'),
  2818.                     'active' => $salesSelectedProductType == ProductType::PRODUCT_TYPE_ID_MONITOR,
  2819.                     'icon'   => '/theme/images/category/monitor-quicklink.png',
  2820.                 ],
  2821.                 ProductType::PRODUCT_TYPE_ID_SMARTPHONE => [
  2822.                     'href'   => '?sfpt=' . ProductType::PRODUCT_TYPE_ID_SMARTPHONE,
  2823.                     'title'  => $translator->trans('Mobile phones'),
  2824.                     'active' => $salesSelectedProductType == ProductType::PRODUCT_TYPE_ID_SMARTPHONE,
  2825.                     'icon'   => '/theme/images/category/mobile-200x150.png',
  2826.                 ],
  2827.                 ProductType::PRODUCT_TYPE_ID_TABLET     => [
  2828.                     'href'   => '?sfpt=' . ProductType::PRODUCT_TYPE_ID_TABLET,
  2829.                     'title'  => $translator->trans('Tablets'),
  2830.                     'active' => $salesSelectedProductType == ProductType::PRODUCT_TYPE_ID_TABLET,
  2831.                     'icon'   => '/theme/images/category/tablet-200x150.png',
  2832.                 ],
  2833.                 ProductType::PRODUCT_TYPE_ID_OTHER      => [
  2834.                     'href'   => '?sfpt=' . ProductType::PRODUCT_TYPE_ID_OTHER,
  2835.                     'title'  => $translator->trans('Other'),
  2836.                     'active' => $salesSelectedProductType == ProductType::PRODUCT_TYPE_ID_OTHER,
  2837.                     'icon'   => '/theme/images/category/docking-station-200x150px.png',
  2838.                 ],
  2839.             ];
  2840.             $data['header_productTypes'] = $productTypes;
  2841.         }
  2842.         $data['header'] = $this->getHeader($request);
  2843.         $data['footer'] = $this->getFooter($request);
  2844.         $data['contentBottom'] = $this->getContentBottom($request, 'category_show');
  2845.         $data['showAdminLoginPanel'] = $request->getSession()->get('isAdminLogin');
  2846.         // Sort By
  2847.         $data['sortOrders'] = $this->getSortOrders($translator);
  2848.         // Limit
  2849.         $data['limits'] = [12, 24, 48, 96];
  2850.         if ($reGenerateCache) {
  2851.             $data['regenerateCache'] = self::REGENERATE_CACHE_TOKEN;
  2852.         }
  2853.         if (in_array($domain->getId(), [Domain::DOMAIN_ID_RT_SK, Domain::DOMAIN_ID_RT_CZ])) {
  2854.             $heureka = new Heureka($this->twig);
  2855.             $data['heurekaSak'] = $heureka->getSakForScript($domain->getLanguage()->getCode());
  2856.         }
  2857.         $data['isBlackFriday'] = false;
  2858.         if ($blackFridayDateIsActive && in_array($categoryId, [642, 643, 644, 645]) ) {
  2859.             $data['isBlackFriday'] = true;
  2860.         }
  2861.         return $this->render('AtechNetCoreBundle/Product/category.html.twig', $data);
  2862.     }
  2863.     /**
  2864.      * @Route("/latest",                                        name="latest_products", defaults={"_locale":""})
  2865.      * @Route("/{_locale<%supported_locales%>?}/latest",        name="latest_products_locale", defaults={"_locale":""})
  2866.      * @Route("/ujdonsagok",                                    name="latest_products_hu", defaults={"_locale":""})
  2867.      * @Route("/{_locale<%supported_locales%>?}/ujdonsagok",    name="latest_products_hu_locale", defaults={"_locale":""})
  2868.      * @Route("/novinky",                                       name="latest_products_sk", defaults={"_locale":""})
  2869.      * @Route("/{_locale<%supported_locales%>?}/novinky",       name="latest_products_sk_locale", defaults={"_locale":""})
  2870.      * @Route("/novinky",                                       name="latest_products_cz", defaults={"_locale":""})
  2871.      * @Route("/{_locale<%supported_locales%>?}/novinky",       name="latest_products_cz_locale", defaults={"_locale":""})
  2872.      * @Route("/latest",                                        name="latest_products_en", defaults={"_locale":""})
  2873.      * @Route("/{_locale<%supported_locales%>?}/latest",        name="latest_products_en_locale", defaults={"_locale":""})
  2874.      * @param Request $request
  2875.      * @return Response
  2876.      * @throws \Exception
  2877.      */
  2878.     public function latestListAction(Request $request): Response
  2879.     {
  2880.         if ($this->kernel->getEnvironment() == 'dev')
  2881.         {
  2882.             ini_set('memory_limit', '1G');
  2883.         }
  2884.         $canRegenerateCache = $request->get('regenerate-cache') == self::REGENERATE_CACHE_TOKEN ?? false;
  2885.         $regenerateWholeSaleDomain = $canRegenerateCache && ($request->get('wholesale') ?? false);
  2886.         $entityManager = $this->getEntityManager();
  2887.         $reGenerateCache = $canRegenerateCache || $regenerateWholeSaleDomain;
  2888.         $request->getSession()->set('cartBackToProductsLink', $this->generateUrl('latest_products'));
  2889.         $translator = $this->getTranslator();
  2890.         $multiStore = $this->getMultiStoreHelper($request);
  2891.         $seoUrlHelper = $this->getSeoUrlHelper($request);
  2892.         $language = $multiStore->getLanguage();
  2893.         $defaultLanguage = $multiStore->getDefaultLanguage();
  2894.         $data['customerTypeId'] = $request->getSession()->get('customerTypeId');
  2895.         $additionalSeoTitle = '';
  2896.         $domainId = $regenerateWholeSaleDomain ? Domain::getRetailWholesaleDomainPairs()[$multiStore->getDomainId()] : $multiStore->getDomainId();
  2897.         $domain = $entityManager->getRepository(Domain::class)->findOneById($domainId);
  2898.         $indexable = null;
  2899.         // Filter CategoryPage
  2900.         $filterCategory = $request->get('filterCategory');
  2901.         if ($filterCategory) {
  2902.             $categoryInfo = $entityManager->getRepository(CategoryPage::class)->findOneById($filterCategory);
  2903.             $indexable = $categoryInfo->isIndexable();
  2904.             $data['categoryId'] = $filterCategory;
  2905.         }
  2906.         // Filter ProductType
  2907.         if ($request->get('fpt')) {
  2908.             $filterProductType = $request->get('fpt');
  2909.             $indexable = false;
  2910.         } else {
  2911.             $filterProductType = null;
  2912.         }
  2913.         // Filter Vendor
  2914.         if ($request->get('fv')) {
  2915.             $filterVendor = $request->get('fv');
  2916.             $indexable = false;
  2917.         } else {
  2918.             $filterVendor = null;
  2919.         }
  2920.         // Filter Attribute
  2921.         if ($request->get('fa')) {
  2922.             $filterAttribute = $request->get('fa');
  2923.             $indexable = false;
  2924.         } else {
  2925.             $filterAttribute = null;
  2926.         }
  2927.         // Filter Price
  2928.         if ($request->get('fp')) {
  2929.             $currency = $domain->getCurrency();
  2930.             $filterPrice = explode('-', $request->get('fp'));
  2931.             if (!empty($filterPrice[0])) {
  2932.                 $filterPriceMin = floor((float)$filterPrice[0]);
  2933.             } else {
  2934.                 $filterPriceMin = null;
  2935.             }
  2936.             if (!empty($filterPrice[1])) {
  2937.                 $filterPriceMax = ceil((float)$filterPrice[1]);
  2938.             } else {
  2939.                 $filterPriceMax = null;
  2940.             }
  2941.             if ($defaultLanguage->getCode() == 'sk') {
  2942.                 $additionalSeoTitle .= ', ' . $translator->trans('from') . ' ' . $filterPriceMin . ' ' . $currency . ' ' . $translator->trans('to') . ' ' . $filterPriceMax . ' ' . $currency;
  2943.             } else {
  2944.                 $additionalSeoTitle .= ', ' . $filterPriceMin . ' ' . $currency . ' - ' . $filterPriceMax . ' ' . $currency;
  2945.             }
  2946.         } else {
  2947.             $filterPriceMin = $filterPriceMax = null;
  2948.         }
  2949.         // Filter Discounted
  2950.         if ($request->get('fd')) {
  2951.             $filterDiscounted = (int)$request->get('fd');
  2952.             $additionalSeoTitle .= ', ' . $translator->trans('discounted products');
  2953.         } else {
  2954.             $filterDiscounted = null;
  2955.         }
  2956.         // Filter Last Pieces
  2957.         if ($request->get('fl')) {
  2958.             $filterLastPieces = (int)$request->get('fl');
  2959.             $additionalSeoTitle .= ', ' . $translator->trans('last pieces');
  2960.         } else {
  2961.             $filterLastPieces = null;
  2962.         }
  2963.         // Sort
  2964.         if ($request->get('sort')) {
  2965.             $sort = $request->get('sort');
  2966.             $indexable = false;
  2967.         } else {
  2968.             $sort = 'created';
  2969.         }
  2970.         // Order
  2971.         if ($request->get('order')) {
  2972.             $order = $request->get('order');
  2973.             $indexable = false;
  2974.         } else {
  2975.             $order = 'desc';
  2976.         }
  2977.         // Limit
  2978.         if ($request->get('limit')) {
  2979.             $limit = $request->get('limit');
  2980.             $indexable = false;
  2981.         } else {
  2982.             $limit = 24;
  2983.         }
  2984.         if ($request->query->count() > 0 && $request->query->count() != 1 && !is_null($request->query->get('page'))) {
  2985.             $indexable = false;
  2986.         }
  2987.         // Page
  2988.         if ($request->get('page')) {
  2989.             $page = $request->get('page');
  2990.             $additionalSeoTitle .= ', ' . $page . '.' . $translator->trans('page');
  2991.         } else {
  2992.             $page = 1;
  2993.         }
  2994.         $data['breadcrumbs'] = [];
  2995.         $data['breadcrumbs'][] = $this->getBreadCrumbsBase($request);
  2996.         $translator = $this->getTranslator();
  2997.         $data['seoTitle'] = $translator->trans('Latest products') . $additionalSeoTitle;
  2998.         if (empty($data['seoTitle'])) {
  2999.             $data['seoTitle'] = $translator->trans('Latest products');
  3000.         }
  3001.         $data['seoDescription'] = $additionalSeoTitle != '' ? ' ' . ucfirst(substr($additionalSeoTitle, 2)) . '.' : '';
  3002.         $data['title'] = $translator->trans('Latest products') . $additionalSeoTitle;
  3003.         $data['indexable'] = $indexable;
  3004.         $data['categories'] = [];
  3005.         $data['popularItems'] = [];
  3006.         $filterData = [
  3007.             'domainId' => $domainId,
  3008.             'filterCategories' => $filterCategory,
  3009.             'filterProductType' => $filterProductType,
  3010.             'filterVendor' => $filterVendor,
  3011.             'filterAttribute' => $filterAttribute,
  3012.             'filterPriceMin' => $filterPriceMin,
  3013.             'filterPriceMax' => $filterPriceMax,
  3014.             'filterDiscounted' => $filterDiscounted,
  3015.             'filterLastPieces' => $filterLastPieces,
  3016.             'sort' => $sort,
  3017.             'order' => $order,
  3018.             'start' => ($page - 1) * $limit,
  3019.             'limit' => $limit,
  3020.             'language' => $language->getCode(),
  3021.             'cacheVer' => 3,
  3022.             'isNewProductPage' => true,
  3023.         ];
  3024.         // productTypes
  3025.         $data['pagination'] = [];
  3026.         $data['categoryListLinks'] = [];
  3027.         $data['partnerLoginRedirect'] = false;
  3028.         if (!is_null($request->query->get('partner-link')) && $request->query->get('partner-link') == 1 && !$this->getLoginHelper($request)->isLoggedIn()) {
  3029.             $data['partnerLoginRedirectRoute'] = $this->generateUrl('partner_login');
  3030.             $data['partnerLoginRedirect'] = true;
  3031.         }
  3032.         $total = $this->getProductHelper($request)->getTotalByFilters($filterData);
  3033.         $arguments = [];
  3034.         $arguments['path'] = $filterCategory;
  3035.         $arguments['isBazaar'] = $categoryInfo->isShowOnlyBazaar();
  3036.         if (!is_null($filterCategory)) {
  3037.             $arguments['filterCategory'] = $filterCategory;
  3038.         }
  3039.         if (!is_null($filterProductType)) {
  3040.             $arguments['fpt'] = $filterProductType;
  3041.         }
  3042.         if (!is_null($filterVendor)) {
  3043.             $arguments['fv'] = $filterVendor;
  3044.         }
  3045.         if (!is_null($filterAttribute)) {
  3046.             foreach ($filterAttribute as $key => $value) {
  3047.                 $arguments['fa[' . $key . ']'] = $value;
  3048.             }
  3049.         }
  3050.         if (!is_null($filterPriceMin) && !is_null($filterPriceMax)) {
  3051.             $arguments['fp'] = $filterPriceMin . '-' . $filterPriceMax;
  3052.         } elseif (!is_null($filterPriceMin) && is_null($filterPriceMax)) {
  3053.             $arguments['fp'] = $filterPriceMin . '-0';
  3054.         } elseif (is_null($filterPriceMin) && !is_null($filterPriceMax)) {
  3055.             $arguments['fp'] = '0-' . $filterPriceMax;
  3056.         }
  3057.         if (!is_null($filterDiscounted)) {
  3058.             $arguments['fd'] = $filterDiscounted;
  3059.         }
  3060.         if (!is_null($filterLastPieces)) {
  3061.             $arguments['fl'] = $filterLastPieces;
  3062.         }
  3063.         if ($request->get('sort')) {
  3064.             $arguments['sort'] = $sort;
  3065.         }
  3066.         if ($request->get('order')) {
  3067.             $arguments['order'] = $order;
  3068.         }
  3069.         if ($request->get('limit')) {
  3070.             $arguments['limit'] = $limit;
  3071.         }
  3072.         $arguments['page'] = '{page}';
  3073.         $data['pagination'] = [
  3074.             'total' => $total,
  3075.             'page' => $page,
  3076.             'limit' => $limit,
  3077.             'moreButton' => true,
  3078.             'url' => $this->url($request)->link('category', $arguments),
  3079.         ];
  3080.         if ($page == 1) {
  3081.             $arguments['page'] = 2;
  3082.             $data['categoryListLinks']['next'] = $this->url($request)->link('category', $arguments);
  3083.         }
  3084.         if ($page > 1) {
  3085.             if ($page == 2) {
  3086.                 unset($arguments['page']);
  3087.             } else {
  3088.                 $arguments['page'] = $page - 1;
  3089.             }
  3090.             $data['categoryListLinks']['prev'] = $this->url($request)->link('category', $arguments);
  3091.             if ($data['pagination']['total'] > 0 && $page < round($data['pagination']['total'] / $data['pagination']['limit'], PHP_ROUND_HALF_UP)) {
  3092.                 $arguments['page'] = $page + 1;
  3093.                 $data['categoryListLinks']['next'] = $this->url($request)->link('category', $arguments);
  3094.             }
  3095.         }
  3096.         // 404 Page if Page Number exceeded
  3097.         if ($page != 1 && $page > ceil($total / $limit)) {
  3098.             return $this->forward('App\AtechNet\CoreBundle\Controller\DefaultController::notFoundAction');
  3099.         }
  3100.         $filterDataForBuildingFilterOptions = $filterData;
  3101.         $filterDataForBuildingFilterOptionsForFilter = $filterDataForBuildingFilterOptions;
  3102.         unset($filterDataForBuildingFilterOptions['filterPriceMin']);
  3103.         unset($filterDataForBuildingFilterOptions['filterPriceMax']);
  3104.         unset($filterDataForBuildingFilterOptions['filterAttribute']);
  3105.         $cache = $this->cache;
  3106.         $filtersCacheKey = 'category.v4.' . $domainId . '.' . $language->getCode() . '.' . $filterCategory . '.' . $total . md5(serialize($filterDataForBuildingFilterOptions));
  3107.         $filteredCacheItem = $cache->getItem($filtersCacheKey);
  3108.         if (!$filteredCacheItem->isHit() || $reGenerateCache) {
  3109.             $filters = $this->getProductHelper($request)->buildFilterOptions($filterDataForBuildingFilterOptionsForFilter);
  3110.             $filteredCacheItem->set($filters);
  3111.             $filteredCacheItem->expiresAfter(self::CACHE_LIFETIME_1_DAY);
  3112.             $cache->save($filteredCacheItem);
  3113.         } else {
  3114.             $filters = $filteredCacheItem->get();
  3115.         }
  3116.         $data['filters'] = $filters;
  3117.         // For product list ajax-request
  3118.         $data['filterData'] = $filterData;
  3119.         // Filter Action
  3120.         $data['action'] = $this->url($request)->link('category', $arguments);
  3121.         $data['currency'] = $domain->getCurrency();
  3122.         $data['precision'] = $domain->getPricePrecision();
  3123.         $data['filterProductType'] = [];
  3124.         if (!is_null($filterProductType)) {
  3125.             $data['filterProductType'] = explode(',', $filterProductType);
  3126.         }
  3127.         $data['filterVendor'] = [];
  3128.         if (!is_null($filterVendor)) {
  3129.             $data['filterVendor'] = explode(',', $filterVendor);
  3130.         }
  3131.         $data['filterAttribute'] = [];
  3132.         if (!is_null($filterAttribute)) {
  3133.             foreach ($filterAttribute as $attribute) {
  3134.                 $options = explode(',', $attribute);
  3135.                 foreach ($options as $option) {
  3136.                     array_push($data['filterAttribute'], $option);
  3137.                 }
  3138.             }
  3139.         }
  3140.         if (!is_null($filterPriceMin)) {
  3141.             $data['filterPriceMin'] = $filterPriceMin;
  3142.         } else {
  3143.             $data['filterPriceMin'] = false;
  3144.         }
  3145.         if (!is_null($filterPriceMax)) {
  3146.             $data['filterPriceMax'] = $filterPriceMax;
  3147.         } else {
  3148.             $data['filterPriceMax'] = false;
  3149.         }
  3150.         if (!is_null($filterDiscounted)) {
  3151.             $data['filterDiscounted'] = $filterDiscounted;
  3152.         } else {
  3153.             $data['filterDiscounted'] = false;
  3154.         }
  3155.         if (!is_null($filterLastPieces)) {
  3156.             $data['filterLastPieces'] = $filterLastPieces;
  3157.         } else {
  3158.             $data['filterLastPieces'] = false;
  3159.         }
  3160.         // Arguments
  3161.         $arguments = [];
  3162.         $arguments['path'] = $filterCategory;
  3163.         $arguments['isBazaar'] = $categoryInfo->isShowOnlyBazaar();
  3164.         if (!is_null($filterCategory)) {
  3165.             $arguments['filterCategory'] = $filterCategory;
  3166.         }
  3167.         if (!is_null($filterProductType)) {
  3168.             $arguments['fpt'] = $filterProductType;
  3169.         }
  3170.         if (!is_null($filterVendor)) {
  3171.             $arguments['fv'] = $filterVendor;
  3172.         }
  3173.         if (!is_null($filterAttribute)) {
  3174.             foreach ($filterAttribute as $key => $value) {
  3175.                 $arguments['fa[' . $key . ']'] = $value;
  3176.             }
  3177.         }
  3178.         if (!is_null($filterPriceMin) && !is_null($filterPriceMax)) {
  3179.             $arguments['fp'] = $filterPriceMin . '-' . $filterPriceMax;
  3180.         } elseif (!is_null($filterPriceMin) && is_null($filterPriceMax)) {
  3181.             $arguments['fp'] = $filterPriceMin . '-0';
  3182.         } elseif (is_null($filterPriceMin) && !is_null($filterPriceMax)) {
  3183.             $arguments['fp'] = '0-' . $filterPriceMax;
  3184.         }
  3185.         if (!is_null($filterDiscounted)) {
  3186.             $arguments['fd'] = $filterDiscounted;
  3187.         }
  3188.         if (!is_null($filterLastPieces)) {
  3189.             $arguments['fl'] = $filterLastPieces;
  3190.         }
  3191.         if ($request->get('sort')) {
  3192.             $arguments['sort'] = $sort;
  3193.         }
  3194.         if ($request->get('order')) {
  3195.             $arguments['order'] = $order;
  3196.         }
  3197.         if ($request->get('limit')) {
  3198.             $arguments['limit'] = $limit;
  3199.         }
  3200.         $data['sort'] = $sort;
  3201.         $data['order'] = $order;
  3202.         $data['limit'] = $limit;
  3203.         $data['quality_info_link'] = $this->getQualityInfoLink($domainId, $seoUrlHelper);
  3204.         $data['salesManager'] = [];
  3205.         if ($data['customerTypeId'] == MultiStore::CUSTOMER_TYPE_WHOLESALE) {
  3206.             $loggedInCustomer = $this->getLoginHelper($request)->getLoggedInCustomer();
  3207.             $salesManager = $loggedInCustomer->getSalesManager();
  3208.             if (!is_null($salesManager)) {
  3209.                 $data['salesManager']['name'] = $salesManager->getFirstName();
  3210.                 $data['salesManager']['username'] = $salesManager->getUsername();
  3211.                 $data['salesManager']['phone'] = $salesManager->getPhone();
  3212.             }
  3213.         }
  3214.         $data['domainLanguageCode'] = $domain->getLanguage()->getCode();
  3215.         $data['webshop_phone_number'] = $this->getContactInfos()['phone.webshop.' . $domain->getLanguage()->getCode() . '.' . $domain->getType()];
  3216.         //-> Canonical Link
  3217.         $canonicalUrl = $seoUrlHelper->link('category', [
  3218.             'path'      => $filterCategory,
  3219.             'isBazaar'  => $categoryInfo->isShowOnlyBazaar()
  3220.         ]);
  3221.         $data['canonical_link'] = $canonicalUrl != $request->getUri() ? $canonicalUrl : '';
  3222.         //<- Canonical Link
  3223.         $data['header'] = $this->getHeader($request);
  3224.         $data['footer'] = $this->getFooter($request);
  3225.         $data['contentBottom'] = $this->getContentBottom($request, 'category_show');
  3226.         $data['showAdminLoginPanel'] = $request->getSession()->get('isAdminLogin');
  3227.         // Sort By
  3228.         $data['sortOrders'] = $this->getSortOrders($translator);
  3229.         // Limit
  3230.         $data['limits'] = [12, 24, 48, 96];
  3231.         if ($reGenerateCache) {
  3232.             $data['regenerateCache'] = self::REGENERATE_CACHE_TOKEN;
  3233.         }
  3234.         return $this->render('AtechNetCoreBundle/Product/latestList.html.twig', $data);
  3235.     }
  3236.     private function getQualityInfoLink($domainId, $seoUrlHelper)
  3237.     {
  3238.         $link = '';
  3239.         switch ($domainId) {
  3240.             case Domain::DOMAIN_ID_RT_SK:
  3241.             case Domain::DOMAIN_ID_WS_SK:
  3242.                 $link = $seoUrlHelper->link('page', [
  3243.                     'static_id' => 11,
  3244.                 ]);
  3245.                 break;
  3246.             case Domain::DOMAIN_ID_RT_HU:
  3247.             case Domain::DOMAIN_ID_WS_HU:
  3248.                 $link = $seoUrlHelper->link('page', [
  3249.                     'static_id' => 27,
  3250.                 ]);
  3251.                 break;
  3252.             case Domain::DOMAIN_ID_RT_CZ:
  3253.             case Domain::DOMAIN_ID_WS_CZ:
  3254.                 $link = $seoUrlHelper->link('page', [
  3255.                     'static_id' => 60,
  3256.                 ]);
  3257.                 break;
  3258.             default:
  3259.                 $link = '';
  3260.                 break;
  3261.         }
  3262.         return $link;
  3263.     }
  3264.     private function getSortOrders($translator): array
  3265.     {
  3266.         return [
  3267.             [
  3268.                 'text' => $translator->trans('low to high'),
  3269.                 'value' => 'price-asc',
  3270.                 'sort' => 'price',
  3271.                 'order' => 'asc',
  3272.             ],
  3273.             [
  3274.                 'text' => $translator->trans('high to low'),
  3275.                 'value' => 'price-desc',
  3276.                 'sort' => 'price',
  3277.                 'order' => 'desc',
  3278.             ],
  3279.             [
  3280.                 'text' => $translator->trans('most popular'),
  3281.                 'value' => 'popular-desc',
  3282.                 'sort' => 'popular',
  3283.                 'order' => 'desc',
  3284.             ],
  3285.             [
  3286.                 'text' => $translator->trans('Last added products'),
  3287.                 'value' => 'created-desc',
  3288.                 'sort' => 'created',
  3289.                 'order' => 'desc',
  3290.             ],
  3291.             [
  3292.                 'text' => $translator->trans('By name'),
  3293.                 'value' => 'name-asc',
  3294.                 'sort' => 'name',
  3295.                 'order' => 'asc',
  3296.             ],
  3297.         ];
  3298.     }
  3299.     /**
  3300.      * @Route("/product/get/list", name="product_list_ajax", defaults={"_locale":""})
  3301.      * @Route("/{_locale<%supported_locales%>?}/product/get/list", name="product_list_ajax_locale", defaults={"_locale":""})
  3302.      * @param Request $request
  3303.      * @return JsonResponse
  3304.      * @throws \Exception
  3305.      */
  3306.     public function listAjaxAction(Request $request): Response
  3307.     {
  3308.         $domain = $this->getMultiStoreHelper($request)->getDomain();
  3309.         $filterData = $request->query->all();
  3310.         if ($this->getEnvironment() == 'prod') {
  3311.             \Sentry\configureScope(function (\Sentry\State\Scope $scope): void {
  3312.                 $scope->setUser([
  3313.                     'ip_address' => $_SERVER['REMOTE_ADDR'],
  3314.                 ]);
  3315.             });
  3316.         }
  3317.         // Filter Price
  3318.         if ($filterData['fp']) {
  3319.             $filterPrice = explode('-', $filterData['fp']);
  3320.             if (!empty($filterPrice[0])) {
  3321.                 $filterPriceMin = floor((float)str_replace(' ', '', $filterPrice[0]));
  3322.             } else {
  3323.                 $filterPriceMin = null;
  3324.             }
  3325.             if (!empty($filterPrice[1])) {
  3326.                 $filterPriceMax = floor((float)str_replace(' ', '', $filterPrice[1]));
  3327.             } else {
  3328.                 $filterPriceMax = null;
  3329.             }
  3330.         } else {
  3331.             $filterPriceMin = $filterPriceMax = null;
  3332.         }
  3333.         if (isset($filterData['fcm'])) {
  3334.             $filterCpuMark = explode('-', $filterData['fcm']);
  3335.             if (!empty($filterCpuMark[0])) {
  3336.                 $filterCpuMarkMin = $filterCpuMark[0];
  3337.             } else {
  3338.                 $filterCpuMarkMin = null;
  3339.             }
  3340.             if (!empty($filterCpuMark[1])) {
  3341.                 $filterCpuMarkMax = $filterCpuMark[1];
  3342.             } else {
  3343.                 $filterCpuMarkMax = null;
  3344.             }
  3345.         } else {
  3346.             $filterCpuMarkMin = $filterCpuMarkMax = null;
  3347.         }
  3348.         $showOnlyDiscounted = $filterData['showOnlyDiscounted'];
  3349.         // Filter Discounted
  3350.         if ($filterData['fd'] != '' || $showOnlyDiscounted) {
  3351.             $filterDiscounted = $showOnlyDiscounted ? 1 : (int)$filterData['fd'];
  3352.         } else {
  3353.             $filterDiscounted = null;
  3354.         }
  3355.         $isNewProductPage = (bool)isset($filterData['isNewProductPage']) ?: false;
  3356.         $categoryId = $filterData[$isNewProductPage ? 'filterCategory' : 'filterCategoryId'];
  3357.         if (isset($filterData['sfpt']) && is_numeric($filterData['sfpt'])) {
  3358.             $filterProductType = $filterData['sfpt'] ?? '';
  3359.         } else {
  3360.             $filterProductType = $filterData['fpt'] ?? '';
  3361.         }
  3362.         $filterVendor = $filterData['fv'] ?? '';
  3363.         $filterAttribute = $filterData['fa'] ? json_decode($filterData['fa'], true) : null;
  3364.         $filterLastPieces = (int)$filterData['fl'] ? $filterData['fl'] : '';
  3365.         $sort = 'price';
  3366.         
  3367.         if ($filterData['sort']) {
  3368.             if (in_array($filterData['sort'], ['price', 'created', 'name', 'popular'])) {
  3369.                 $sort = $filterData['sort'];
  3370.             }
  3371.         }
  3372.         $order = 'asc';
  3373.         if ($filterData['order']) {
  3374.             if (in_array($filterData['order'], ['asc', 'desc'])) {
  3375.                 $order = $filterData['order'];
  3376.             }
  3377.         }
  3378.         $limit = (int)$filterData['limit'] ?? 23;
  3379.         $page = (int)$filterData['page'] ?? 1;
  3380.         $canRegenerateCache = isset($filterData['regenerateCache']) && $filterData['regenerateCache'] == self::REGENERATE_CACHE_TOKEN ?? false;
  3381.         $regenerateWholeSaleDomain = $canRegenerateCache && ($filterData['isWholesale'] ?? false);
  3382.         $reGenerateCache = $canRegenerateCache || $regenerateWholeSaleDomain || $this->getEnvironment() == 'dev';
  3383.         $productTypes = [];
  3384.         //sale filter change for the other category
  3385.         if (in_array($categoryId, CategoryPage::SALE_CATEGORY_PAGES)
  3386.             && !is_null($filterProductType)
  3387.             && $filterProductType == ProductType::PRODUCT_TYPE_ID_OTHER)
  3388.         {
  3389.             $categoryInfo = $this->getEntityManager()->getRepository(CategoryPage::class)
  3390.                 ->findOneById($categoryId);
  3391.             foreach ($categoryInfo->getProducts() as $product) {
  3392.                 $productType = $product->getType();
  3393.                 if (in_array($productType->getId(), ProductType::getSaleProductTypeFilterTypes())) {
  3394.                     continue;
  3395.                 }
  3396.                 if (!isset($productTypes[$productType->getId()])) {
  3397.                     $productTypes[$productType->getId()] = $productType->getId();
  3398.                 }
  3399.             }
  3400.             $filterProductType = implode(',', $productTypes);
  3401.             if (empty($filterProductType)) {
  3402.                 $filterProductType = ProductType::PRODUCT_TYPE_ID_OTHER;
  3403.             }
  3404.         }
  3405.         $filterData = [
  3406.             'domainId' => $regenerateWholeSaleDomain ? Domain::getRetailWholesaleDomainPairs()[$domain->getId()] : $domain->getId(),
  3407.             'filterCategoryId' => $categoryId,
  3408.             'filterProductType' => $filterProductType,
  3409.             'filterVendor' => $filterVendor,
  3410.             'filterAttribute' => $filterAttribute,
  3411.             'filterPriceMin' => $filterPriceMin,
  3412.             'filterPriceMax' => $filterPriceMax,
  3413.             'filterCpuMarkMin'  => $filterCpuMarkMin,
  3414.             'filterCpuMarkMax'  => $filterCpuMarkMax,
  3415.             'filterDiscounted' => $filterDiscounted,
  3416.             'filterLastPieces' => $filterLastPieces,
  3417.             'sort' => $sort,
  3418.             'order' => $order,
  3419.             'start' => ($page - 1) * $limit,
  3420.             'limit' => $limit,
  3421.             'language' => $domain->getLanguage()->getCode(),
  3422.             'cacheVer' => 3,
  3423.         ];
  3424.         if ($isNewProductPage) {
  3425.             unset($filterData['filterCategoryId']);
  3426.             $filterData['filterCategories'] = $categoryId;
  3427.         }
  3428.         $data['currency'] = $domain->getCurrency();
  3429.         $data['precision'] = $domain->getPricePrecision();
  3430.         $data['filterProductType'] = $filterProductType ? explode(',', $filterProductType) : [];
  3431.         $data['filterVendor'] = $filterVendor ? explode(',', $filterVendor) : [];
  3432.         $data['filterAttribute'] = [];
  3433.         if (!is_null($filterAttribute)) {
  3434.             foreach ($filterAttribute as $attribute) {
  3435.                 $options = explode(',', $attribute);
  3436.                 foreach ($options as $option) {
  3437.                     array_push($data['filterAttribute'], $option);
  3438.                 }
  3439.             }
  3440.         }
  3441.         $data['filterPriceMin'] = $filterPriceMin ?? false;
  3442.         $data['filterPriceMax'] = $filterPriceMax ?? false;
  3443.         $data['filterDiscounted'] = $filterDiscounted ?? false;
  3444.         $data['filterLastPieces'] = $filterLastPieces ?? false;
  3445.         $data['products'] = [];
  3446.         $cache = $this->cache;
  3447.         $productsCacheKey = 'products.v16.' . $domain->getId() . '.' . $domain->getLanguage()->getCode() . '.' . $isNewProductPage . '.' . md5(serialize($filterData));
  3448.         $productsCacheItem = $cache->getItem($productsCacheKey);
  3449.         $productsCacheTimeKey = 'products.v16.' . $domain->getId() . '.' . $domain->getLanguage()->getCode() . '.' . $isNewProductPage . '.' . md5(serialize($filterData)) . '.time';
  3450.         $productsCacheTimeItem = $cache->getItem($productsCacheTimeKey);
  3451.         if (!$productsCacheItem->isHit() || $reGenerateCache) {
  3452.             $data['products'] = $isNewProductPage ? $this->getNewProductListByFilter($request, $filterData, $domain) : $this->getProductListByFilter($request, $filterData, $domain);
  3453.             $productsCacheItem->set($data['products']);
  3454.             if ($categoryId == 659) {
  3455.                 $productsCacheItem->expiresAfter(self::CACHE_LIFETIME_15_MINUTES);
  3456.             } else {
  3457.                 $productsCacheItem->expiresAfter(self::CACHE_LIFETIME_12_HOURS);
  3458.             }
  3459.             $cache->save($productsCacheItem);
  3460.             $productsCacheTimeItem->set((new \DateTime('now'))->getTimestamp());
  3461.             $productsCacheTimeItem->expiresAfter(self::CACHE_LIFETIME_12_HOURS);
  3462.             $cache->save($productsCacheTimeItem);
  3463.         } else {
  3464.             $data['products'] = $productsCacheItem->get();
  3465.         }
  3466.         $data['currency'] = $domain->getCurrency();
  3467.         $data['precision'] = $domain->getPricePrecision();
  3468.         $arguments = [];
  3469.         if ($filterData['sort'] != '') {
  3470.             $arguments['sort'] = $filterData['sort'];
  3471.         }
  3472.         if ($filterData['filterProductType'] != '') {
  3473.             $arguments['fpt'] = $filterData['filterProductType'];
  3474.         }
  3475.         if ($filterData['filterVendor'] != '') {
  3476.             $arguments['fv'] = $filterData['filterVendor'];
  3477.         }
  3478.         if ($filterData['filterAttribute'] != '') {
  3479.             foreach ($filterData['filterAttribute'] as $key => $value) {
  3480.                 $arguments['fa[' . $key . ']'] = $value;
  3481.             }
  3482.         }
  3483.         if ($filterData['filterPriceMin'] != '' && $filterData['filterPriceMax'] != '') {
  3484.             $arguments['fp'] = $filterData['filterPriceMin'] . '-' . $filterData['filterPriceMax'];
  3485.         } elseif ($filterData['filterPriceMin'] != '' && $filterData['filterPriceMax'] != '') {
  3486.             $arguments['fp'] = $filterData['filterPriceMin'] . '-0';
  3487.         } elseif ($filterData['filterPriceMin'] != '' && $filterData['filterPriceMax'] != '') {
  3488.             $arguments['fp'] = '0-' . $filterData['filterPriceMax'];
  3489.         }
  3490.         if ($filterData['filterDiscounted'] != '') {
  3491.             $arguments['fd'] = $filterData['filterDiscounted'];
  3492.         }
  3493.         if ($filterData['filterLastPieces'] != '') {
  3494.             $arguments['fl'] = $filterData['filterLastPieces'];
  3495.         }
  3496.         if ($filterData['sort']) {
  3497.             $arguments['sort'] = $sort;
  3498.         }
  3499.         if ($filterData['order'] != '') {
  3500.             $arguments['order'] = $filterData['order'];
  3501.         }
  3502.         if ($filterData['limit'] != '') {
  3503.             $arguments['limit'] = $filterData['limit'];
  3504.         }
  3505.         $arguments['page'] = '{page}';
  3506.         $data['pagination'] = [
  3507.             'total' => $this->getProductHelper($request)->getTotalByFilters($filterData),
  3508.             'page' => $page,
  3509.             'limit' => $arguments['limit'],
  3510.             'moreButton' => true,
  3511.             'url' => $this->url($request)->link('category', $arguments),
  3512.         ];
  3513.         $data['showAdminLoginPanel'] = $request->getSession()->get('isAdminLogin');
  3514.         // Last Update
  3515.         if ($productsCacheTimeItem->isHit()) {
  3516.             $timestamp = $productsCacheTimeItem->get();
  3517.             $data['lastCacheUpdate'] = (new \DateTime())->setTimestamp($timestamp)->format('d.m.Y H:i');
  3518.         }
  3519.         return new JsonResponse($data);
  3520.     }
  3521.     /**
  3522.      * @Route("/product/get/variants", name="product_variants", defaults={"_locale":""})
  3523.      * @Route("/{_locale<%supported_locales%>?}/product/get/variants", name="product_variants_locale", defaults={"_locale":""})
  3524.      * @param Request $request
  3525.      * @return JsonResponse
  3526.      * @throws \Exception
  3527.      */
  3528.     public function variantsAction(Request $request): JsonResponse
  3529.     {
  3530.         $filter = [];
  3531.         $productId = 0;
  3532.         if ($request->get('productId')) {
  3533.             $productId = $request->get('productId');
  3534.         }
  3535.         $translator = $this->getTranslator();
  3536.         $multiStore = $this->getMultiStoreHelper($request);
  3537.         $cache = $this->cache;
  3538.         $cacheKey = 'product.variations.v4.domain.' . $multiStore->getDomain()->getId() . '.' . (int)$productId;
  3539.         $cacheItem = $cache->getItem($cacheKey);
  3540.         $result = [];
  3541.         if ($cacheItem->isHit() && false) {
  3542.             $result = $cacheItem->get();
  3543.         } else {
  3544.             $product = $this->getEntityManager()->getRepository(Product::class)->find($productId);
  3545.             if ($product) {
  3546.                 $filter['vendorId'] = $product->getVendor()->getId();
  3547.                 $filter['name'] = $product->getName();
  3548.                 $filter['typeId'] = $product->getType()->getId();
  3549.                 $filter['productId'] = $product->getId();
  3550.                 $filter['basePrice'] = $multiStore->getBasePrice();
  3551.                 $result = $this->getProductHelper($request)->getVariantsForFilter($this->getSeoUrlHelper($request), $translator, $filter);
  3552.                 $cacheItem->set($result);
  3553.                 $cacheItem->expiresAfter(self::CACHE_LIFETIME_12_HOURS);
  3554.                 $cache->save($cacheItem);
  3555.             }
  3556.         }
  3557.         return new JsonResponse($result);
  3558.     }
  3559.     /**
  3560.      * @Route("/product/live/search", name="product_live_search", defaults={"_locale":""})
  3561.      * @Route("/{_locale<%supported_locales%>?}/product/live/search", name="product_live_search_locale", defaults={"_locale":""})
  3562.      * @param Request $request
  3563.      * @return JsonResponse
  3564.      * @throws \Exception
  3565.      */
  3566.     public function liveSearchAction(Request $request)
  3567.     {
  3568.         // JSON
  3569.         $json = [];
  3570.         // Search Term
  3571.         if ($request->get('fs')) {
  3572.             $filterSearch = trim($request->get('fs'));
  3573.         } else {
  3574.             $filterSearch = null;
  3575.         }
  3576.         // Stopwatch
  3577.         $stopwatch = new Stopwatch();
  3578.         // Debug
  3579.         $json['debug'] = [];
  3580.         // Start Event
  3581.         $stopwatch->start('requirements');
  3582.         // Entity Manager
  3583.         $entityManager = $this->getEntityManager();
  3584.         // Connecion
  3585.         $connection = $entityManager->getConnection();
  3586.         // System Translator
  3587.         $translator = $this->getTranslator();
  3588.         // Tokenizer
  3589.         $tokenizer = $this->getSeoUrlHelper($request);
  3590.         // Multi-Store
  3591.         $multiStore = $this->getMultiStoreHelper($request);
  3592.         // Cache
  3593.         $cache = $this->cache;
  3594.         // Domain
  3595.         $cacheKey = SearchHelper::getDomainCacheKey($multiStore->getDomainId());
  3596.         $cacheItem = $cache->getItem($cacheKey);
  3597.         if ($cacheItem->isHit() && is_numeric(($cacheItem->get())->getId())) {
  3598.             $domain = $cacheItem->get();
  3599.         } else {
  3600.             $domain = $entityManager->createQuery("SELECT d, l FROM AtechNetCoreBundle:Domain d JOIN d.language l WHERE d.id = :domain")
  3601.                 ->setParameters([
  3602.                     'domain' => $multiStore->getDomainId(),
  3603.                 ])
  3604.                 ->getSingleResult();
  3605.             $cacheItem->set($domain);
  3606.             $cacheItem->expiresAfter(SearchHelper::CACHE_LIFETIME_7_DAYS);
  3607.             $cache->save($cacheItem);
  3608.         }
  3609.         // Currency
  3610.         $currency = $domain->getCurrency();
  3611.         $precision = $domain->getPricePrecision();
  3612.         // Language
  3613.         $language = $domain->getLanguage();
  3614.         // Search Helper
  3615.         $searchHelper = new SearchHelper($entityManager, $tokenizer, $cache, $domain, $language);
  3616.         // Limit
  3617.         $limit = 5;
  3618.         // Recommend
  3619.         $recommend = false;
  3620.         // Debug
  3621.         $json['debug']['requirements'] = (string)$stopwatch->stop('requirements');
  3622.         //-> Expression
  3623.         // Start Event
  3624.         $stopwatch->start('expression');
  3625.         $i = 0;
  3626.         $expressions = [];
  3627.         $expression = strtok($filterSearch, ' ');
  3628.         while ($expression !== false) {
  3629.             $expressions[] = [
  3630.                 'expression' => $expression,
  3631.                 'slug' => $tokenizer->slug($expression),
  3632.                 'mark' => 'none',
  3633.                 'priority' => (++$i),
  3634.             ];
  3635.             $expression = strtok(' ');
  3636.         }
  3637.         // Add Expression List to Helper
  3638.         $searchHelper->setExpressions($expressions);
  3639.         // Debug
  3640.         $json['debug']['expression'] = (string)$stopwatch->stop('expression');
  3641.         //<- Expression
  3642.         //-> Initialize Search
  3643.         // Start Debug Event
  3644.         $stopwatch->start('initialize');
  3645.         $searchHelper->initialize();
  3646.         // Debug
  3647.         $json['debug']['initialize'] = (string)$stopwatch->stop('initialize');
  3648.         //<- Initialize Search
  3649.         // Vendors
  3650.         $vendors = $searchHelper->getVendors();
  3651.         // Product Types
  3652.         $productTypes = $searchHelper->getProductTypes();
  3653.         // Products
  3654.         $products = $searchHelper->getProducts();
  3655.         //-> Categories
  3656.         // Start Event
  3657.         $stopwatch->start('category');
  3658.         // Category Repository
  3659.         $categoryPageRepository = $entityManager->getRepository(CategoryPage::class);
  3660.         $categoryPageRepository->setSession($request->getSession());
  3661.         // Categories
  3662.         $categories = [];
  3663.         $results = $connection->fetchAllAssociative("SELECT * FROM pages_category WHERE published = '1' AND domain_id = ?", [$domain->getId()], ['integer']);
  3664.         foreach ($results as $result) {
  3665.             // Skip non product category
  3666.             if ((int)$result['type'] !== CategoryPage::CATEGORY_TYPE_PRODUCT) {
  3667.                 continue;
  3668.             }
  3669.             // Skip category with badge
  3670.             if (!empty($result['badges'])) {
  3671.                 continue;
  3672.             }
  3673.             // Skip discounted category
  3674.             if ((int)$result['show_only_discounted'] == 1) {
  3675.                 continue;
  3676.             }
  3677.             // Skip flash sale category
  3678.             if ((int)$result['show_only_flash_sales'] == 1) {
  3679.                 continue;
  3680.             }
  3681.             // Skip bazaar category
  3682.             if ((int)$result['show_only_bazaar'] == 1) {
  3683.                 continue;
  3684.             }
  3685.             // Skip category with product limitation
  3686.             if ((int)$connection->fetchOne("SELECT COUNT(product_id) FROM category_pages_products WHERE category_page_id = ?", [$result['id']], ['integer']) > 0) {
  3687.                 continue;
  3688.             }
  3689.             // Get vendors of category
  3690.             $categoryVendors = array_map(function ($categoryVendor) {
  3691.                 return (int)$categoryVendor['vendor_id'];
  3692.             }, $connection->fetchAllAssociative("SELECT * FROM category_pages_vendors WHERE category_page_id = ?", [$result['id']], ['integer']));
  3693.             // Get product types of category
  3694.             $categoryProductTypes = array_map(function ($categoryProductType) {
  3695.                 return (int)$categoryProductType['product_type_id'];
  3696.             }, $connection->fetchAllAssociative("SELECT * FROM category_pages_product_types WHERE category_page_id = ?", [$result['id']], ['integer']));
  3697.             // Get meta data of category
  3698.             $meta = $connection->fetchAssociative("SELECT title, link FROM pages_meta WHERE language_id = ? AND category_page_id = ?", [$language->getId(), $result['id']], ['integer', 'integer']);
  3699.             if (!empty($meta) && (!empty($categoryVendors) || !empty($categoryProductTypes))) {
  3700.                 // Remove warranty from title
  3701.                 $title = trim(str_replace([
  3702.                     '2 év garanciával', '3 év garanciával', 'garanciával',
  3703.                     's 2-ročnou zárukou', 's 2 letou zárukou',
  3704.                 ], '', $meta['title']));
  3705.                 // Translate Title
  3706.                 if ($multiStore->isLanguageSwitched()) {
  3707.                     // Base Categories
  3708.                     $alternativeCategoryId = SearchHelper::getAlternativeCategory($result['id'], $request->getLocale());
  3709.                     if (!is_null($alternativeCategoryId)) {
  3710.                         // Get meta data of alternative category
  3711.                         $alternativeMeta = $connection->fetchAssociative("SELECT title, link FROM pages_meta WHERE language_id = ? AND category_page_id = ?", [$multiStore->getLanguageId(), $alternativeCategoryId], ['integer', 'integer']);
  3712.     
  3713.                         if (!empty($alternativeMeta)) {
  3714.                             // Remove warranty from alternative title
  3715.                             $title = trim(str_replace([
  3716.                                 '2 év garanciával', '3 év garanciával', 'garanciával',
  3717.                                 's 2-ročnou zárukou', 's 2 letou zárukou',
  3718.                             ], '', $alternativeMeta['title']));
  3719.                         }
  3720.                     }
  3721.                     // Everything else
  3722.                     else {
  3723.                         $categoryPage = $entityManager->getRepository(CategoryPage::class)->findOneById($result['id']);
  3724.                         if ($categoryPage) {
  3725.                             $alternativeCategoryPage = $categoryPageRepository->getAlternativeCategoryByLanguage($categoryPage);
  3726.                             if ($alternativeCategoryPage) {
  3727.                                 $alternativeCategoryMeta = $alternativeCategoryPage->getMetaByLanguage($multiStore->getLanguage());
  3728.                                 if ($alternativeCategoryMeta) {
  3729.                                     // Remove warranty from alternative title
  3730.                                     $title = trim(str_replace([
  3731.                                         '2 év garanciával', '3 év garanciával', 'garanciával',
  3732.                                         's 2-ročnou zárukou', 's 2 letou zárukou',
  3733.                                     ], '', $alternativeCategoryMeta->getTitle()));
  3734.                                 }
  3735.                             }
  3736.                         }
  3737.                     }
  3738.                 }
  3739.                 // Priority
  3740.                 $priority = 0;
  3741.                 // Vendor Priority
  3742.                 $highestPriority = 0;
  3743.                 foreach ($categoryVendors as $vendorId) {
  3744.                     if (isset($vendors[$vendorId])) {
  3745.                         if ($highestPriority < $vendors[$vendorId]['priority']) {
  3746.                             $highestPriority = $vendors[$vendorId]['priority'];
  3747.                         }
  3748.                     }
  3749.                 }
  3750.                 $priority += $highestPriority;
  3751.                 // Product Type Priority
  3752.                 $highestPriority = 0;
  3753.                 foreach ($categoryProductTypes as $productTypeId) {
  3754.                     if (isset($productTypes[$productTypeId])) {
  3755.                         if ($highestPriority < $productTypes[$productTypeId]['priority']) {
  3756.                             $highestPriority = $productTypes[$productTypeId]['priority'];
  3757.                         }
  3758.                     }
  3759.                 }
  3760.                 $priority += $highestPriority;
  3761.                 $categories[(int)$result['id']] = [
  3762.                     'id' => (int)$result['id'],
  3763.                     'title' => $title,
  3764.                     'link' => $meta['link'],
  3765.                     'priority' => $priority,
  3766.                     'vendor' => $categoryVendors,
  3767.                     'productType' => $categoryProductTypes,
  3768.                 ];
  3769.             }
  3770.         }
  3771.         // Sort categories by priority
  3772.         $sortOrder = [];
  3773.         foreach ($categories as $key => $value) {
  3774.             $sortOrder[$key] = $value['priority'];
  3775.         }
  3776.         array_multisort($sortOrder, SORT_DESC, SORT_NUMERIC, $categories);
  3777.         // Debug
  3778.         $json['debug']['category'] = (string)$stopwatch->stop('category');
  3779.         //<- Categories
  3780.         //-> Search
  3781.         // Start Event
  3782.         $stopwatch->start('search');
  3783.         $search = $searchHelper->search();
  3784.         // Recommend
  3785.         if (empty($search['productType']['exact']) && empty($search['productType']['misspelled']) && empty($search['vendor']['exact']) && empty($search['vendor']['misspelled']) && (!empty($search['vendor']['startWith']) || !empty($search['productType']['startWith']))) {
  3786.             $recommend = true;
  3787.         }
  3788.         // Debug
  3789.         $json['debug']['search'] = (string)$stopwatch->stop('search');
  3790.         //<- Search
  3791.         //-> Collection of possible results
  3792.         // Start Event
  3793.         $stopwatch->start('possible-result');
  3794.         // Possible Results
  3795.         $possibleResults = $searchHelper->possibleResults($search);
  3796.         // Featured Vendors
  3797.         $featuredVendors = $searchHelper->getFeaturedVendors();
  3798.         // Featured Product Types
  3799.         $featuredProductTypes = $searchHelper->getFeaturedProductTypes();
  3800.         // Found Products
  3801.         $foundProducts = [];
  3802.         // Index
  3803.         $index = 0;
  3804.         // Group by priority
  3805.         $priorityGroups = [];
  3806.         foreach ($possibleResults as $result) {
  3807.             $priorityGroups[$result['priority']][] = $result;
  3808.         }
  3809.         // Highlight 3 discounted products
  3810.         $highlightProducts = [];
  3811.         foreach ($priorityGroups as $priorityGroup) {
  3812.             foreach ($priorityGroup as $result) {
  3813.                 // Product ID
  3814.                 $productId = (int)$result['id'];
  3815.                 // Product Details
  3816.                 if (!empty($products['all'][$productId])) {
  3817.                     $product = $products['all'][$productId];
  3818.                     if ((int)$product['discounted'] == 1) {
  3819.                         $highlightProducts[] = [
  3820.                             'id' => (int)$result['id'],
  3821.                             'price' => (float)$product['discount'],
  3822.                         ];
  3823.                     }
  3824.                 }
  3825.                 if (count($highlightProducts) == 3) {
  3826.                     break 2;
  3827.                 }
  3828.             }
  3829.             break;
  3830.         }
  3831.         // Sort highlighted discounted products
  3832.         if (count($highlightProducts) > 1) {
  3833.             $sortOrder = [];
  3834.             foreach ($highlightProducts as $key => $value) {
  3835.                 $sortOrder[$key] = $value['price'];
  3836.             }
  3837.             array_multisort($sortOrder, SORT_ASC, SORT_NUMERIC, $highlightProducts);
  3838.         }
  3839.         // Found highlighted discounted Products
  3840.         if (count($highlightProducts) > 0) {
  3841.             $foundProducts = array_map(function ($product) {
  3842.                 return (int)$product['id'];
  3843.             }, $highlightProducts);
  3844.         }
  3845.         // Special products
  3846.         $specialProducts = count($highlightProducts);
  3847.         // Fill with non-special products
  3848.         foreach ($priorityGroups as $priorityGroup) {
  3849.             foreach ($priorityGroup as $result) {
  3850.                 // Product ID
  3851.                 $productId = (int)$result['id'];
  3852.                 if (!in_array($productId, $foundProducts)) {
  3853.                     // Product Details
  3854.                     if (!empty($products['all'][$productId])) {
  3855.                         $product = $products['all'][$productId];
  3856.                         if (count($highlightProducts) == 3 && (int)$product['discounted'] == 0) {
  3857.                             array_push($foundProducts, $productId);
  3858.                         } elseif (count($highlightProducts) < 3 && $specialProducts < 3) {
  3859.                             array_push($foundProducts, $productId);
  3860.                             if ((int)$product['discounted'] == 1) {
  3861.                                 $specialProducts++;
  3862.                             }
  3863.                         } elseif ((int)$product['discounted'] == 0) {
  3864.                             array_push($foundProducts, $productId);
  3865.                         }
  3866.                     }
  3867.                 }
  3868.                 if (count($foundProducts) == $limit) {
  3869.                     break 2;
  3870.                 }
  3871.             }
  3872.         }
  3873.         // Debug
  3874.         $json['debug']['possible-result'] = (string)$stopwatch->stop('possible-result');
  3875.         //<- Collection of possible results
  3876.         // Start Event
  3877.         $stopwatch->start('popular-link');
  3878.         // Popular Categories
  3879.         $popularLinks = [];
  3880.         if (!empty($possibleResults)) {
  3881.             // Clone
  3882.             $clonePossibleResults = $possibleResults;
  3883.             // Index
  3884.             $index = 0;
  3885.             while (!empty($clonePossibleResults) && count($popularLinks) < $limit && ($limit * 3) >= $index) {
  3886.                 // Possible Product
  3887.                 $possibleProduct = array_shift($clonePossibleResults);
  3888.                 if (isset($products['all'][$possibleProduct['id']])) {
  3889.                     $product = $products['all'][$possibleProduct['id']];
  3890.                     foreach ($categories as $category) {
  3891.                         if (in_array((int)$product['vendor_id'], $category['vendor'])) {
  3892.                             $popularLinks[$category['id']] = $category;
  3893.                         }
  3894.                     }
  3895.                     $index++;
  3896.                 }
  3897.             }
  3898.         }
  3899.         // Debug
  3900.         $json['debug']['popular-link'] = (string)$stopwatch->stop('popular-link');
  3901.         //> Blog & Static Pages
  3902.         $stopwatch->start('blog-static-pages');
  3903.         // Blog Posts
  3904.         $foundBlogs = $json['blog'] = [];
  3905.         if (!empty($search['page']['exact'])) {
  3906.             $foundBlogs = array_filter($search['page']['exact'], function ($value) {
  3907.                 return $value['type'] == 'blog';
  3908.             });
  3909.         }
  3910.         if (!empty($search['page']['approximate']) && count($foundBlogs) < 3) {
  3911.             $foundBlogs = array_merge($foundBlogs, array_filter($search['page']['approximate'], function ($value) {
  3912.                 return $value['type'] == 'blog';
  3913.             }));
  3914.         }
  3915.         if (!empty($search['page']['similar']) && count($foundBlogs) < 3) {
  3916.             $foundBlogs = array_merge($foundBlogs, array_filter($search['page']['similar'], function ($value) {
  3917.                 return $value['type'] == 'blog';
  3918.             }));
  3919.         }
  3920.         if (count($foundBlogs) > 0) {
  3921.             $sortOrder = [];
  3922.             foreach ($foundBlogs as $key => $value) {
  3923.                 $sortOrder[$key] = $value['priority'];
  3924.             }
  3925.             array_multisort($sortOrder, SORT_DESC, SORT_NUMERIC, $foundBlogs);
  3926.             foreach ($foundBlogs as $blog) {
  3927.                 $json['blog'][$blog['blog_category_id']] = [
  3928.                     'title' => $blog['title'],
  3929.                     'href' => $this->url($request)->link('blog', [
  3930.                         'blog_id' => $blog['blog_category_id'],
  3931.                     ]),
  3932.                 ];
  3933.                 if (count($json['blog']) >= 3) {
  3934.                     break;
  3935.                 }
  3936.             }
  3937.         }
  3938.         // Static Pages
  3939.         $foundStatic = $json['static'] = [];
  3940.         if (!empty($search['page']['exact'])) {
  3941.             $foundStatic = array_filter($search['page']['exact'], function ($value) {
  3942.                 return $value['type'] == 'static';
  3943.             });
  3944.         }
  3945.         if (!empty($search['page']['approximate']) && count($foundStatic) < 3) {
  3946.             $foundStatic = array_merge($foundStatic, array_filter($search['page']['approximate'], function ($value) {
  3947.                 return $value['type'] == 'static';
  3948.             }));
  3949.         }
  3950.         if (!empty($search['page']['similar']) && count($foundStatic) < 3) {
  3951.             $foundStatic = array_merge($foundStatic, array_filter($search['page']['similar'], function ($value) {
  3952.                 return $value['type'] == 'static';
  3953.             }));
  3954.         }
  3955.         if (count($foundStatic) > 0) {
  3956.             $sortOrder = [];
  3957.             foreach ($foundStatic as $key => $value) {
  3958.                 $sortOrder[$key] = $value['priority'];
  3959.             }
  3960.             array_multisort($sortOrder, SORT_DESC, SORT_NUMERIC, $foundStatic);
  3961.             foreach ($foundStatic as $static) {
  3962.                 $json['static'][$static['static_page_id']] = [
  3963.                     'title' => $static['title'],
  3964.                     'href' => $this->url($request)->link('page', [
  3965.                         'static_id' => $static['static_page_id'],
  3966.                     ]),
  3967.                 ];
  3968.                 if (count($json['static']) >= 3) {
  3969.                     break;
  3970.                 }
  3971.             }
  3972.         }
  3973.         $json['debug']['blog-static-pages'] = (string)$stopwatch->stop('blog-static-pages');
  3974.         //< Blog & Static Pages
  3975.         // Start Event
  3976.         $stopwatch->start('results');
  3977.         // Results
  3978.         if (!empty($foundProducts)) {
  3979.             $placeholder = $this->getImage('placeholder.png', '')->resize(Image::LIVESEARCH_THUMB_WIDTH, Image::LIVESEARCH_THUMB_HEIGHT);
  3980.             // Retrieve product data from cache
  3981.             $products = $validate = $missing = [];
  3982.             foreach ($foundProducts as $productId) {
  3983.                 // Cache
  3984.                 $productCacheKey = ProductHelper::getProductCacheKey($domain->getId(), $request->getLocale(), $productId);
  3985.                 $productCacheItem = $cache->getItem($productCacheKey);
  3986.                 if ($productCacheItem->isHit()) {
  3987.                     $products[$productId] = $productCacheItem->get();
  3988.                     $validate[] = $productId;
  3989.                 } else {
  3990.                     $products[$productId] = [];
  3991.                     $missing[] = $productId;
  3992.                 }
  3993.             }
  3994.             // Validate retrieved product data from cache
  3995.             if (!empty($validate)) {
  3996.                 // Retrieve live data of products for validating
  3997.                 $productsLiveData = $entityManager->createQuery("SELECT p.id, p.available, pm.orderable, pm.active, pm.price, pm.discount, pm.discounted
  3998.                         FROM AtechNetCoreBundle:Product p
  3999.                         LEFT JOIN AtechNetCoreBundle:ProductMeta pm WITH pm.product = p AND pm.domain = :domain
  4000.                         WHERE p.id IN ( :productIds )")
  4001.                     ->setParameters([
  4002.                         'domain' => $domain,
  4003.                         'productIds' => $validate,
  4004.                     ])
  4005.                     ->getResult();
  4006.                 // Compare cached and live data
  4007.                 foreach ($productsLiveData as $productLiveData) {
  4008.                     // Product ID
  4009.                     $productId = (int)$productLiveData['id'];
  4010.                     // Product Cache Data
  4011.                     if (empty($products[$productId])) {
  4012.                         continue;
  4013.                     }
  4014.                     $productCacheData = $products[$productId];
  4015.                     // Compare
  4016.                     $valid = $productCacheData['available'] == $productLiveData['available'] && $productCacheData['orderable'] == $productLiveData['orderable'] && $productCacheData['active'] == $productLiveData['active'] && (int)$productCacheData['rawPriceWoVAT'] == (int)$productLiveData['price'] && (int)$productCacheData['rawDiscountPriceWoVAT'] == (int)$productLiveData['discount'] && $productCacheData['isDiscounted'] == $productLiveData['discounted'];
  4017.                     if (!$valid) {
  4018.                         $products[$productId] = [];
  4019.                         $missing[] = $productId;
  4020.                     }
  4021.                 }
  4022.             }
  4023.             // Retrieve product data from database
  4024.             if (!empty($missing)) {
  4025.                 $productsData = $this->getProductHelper($request)->getStructuredDataForProductsById($missing);
  4026.                 foreach ($productsData as $productData) {
  4027.                     // Data
  4028.                     $data = $this->buildProductViewData($productData, $request, $domain, $entityManager, $multiStore);
  4029.                     // Cache
  4030.                     $productCacheKey = ProductHelper::getProductCacheKey($domain->getId(), $request->getLocale(), $productData['id']);
  4031.                     $productCacheItem = $cache->getItem($productCacheKey);
  4032.                     $productCacheTimeKey = ProductHelper::getProductCacheKey($domain->getId(), $request->getLocale(), $productData['id']) . '.time';
  4033.                     $productCacheTimeItem = $cache->getItem($productCacheTimeKey);
  4034.                     $productCacheItem->set($data);
  4035.                     $productCacheItem->expiresAfter(self::CACHE_LIFETIME_7_DAYS);
  4036.                     $cache->save($productCacheItem);
  4037.                     $productCacheTimeItem->set((new \DateTime('now'))->getTimestamp());
  4038.                     $productCacheTimeItem->expiresAfter(self::CACHE_LIFETIME_7_DAYS);
  4039.                     $cache->save($productCacheTimeItem);
  4040.                     // List
  4041.                     $products[$productData['id']] = $data;
  4042.                 }
  4043.             }
  4044.             foreach ($products as $result) {
  4045.                 $image = $placeholder;
  4046.                 if (!empty($result['images'])) {
  4047.                     $image = $result['images'][0]['additional'];
  4048.                 }
  4049.                 if ($multiStore->getBasePrice() == MultiStore::BASE_PRICE_NET) {
  4050.                     $price = number_format($result['rawPriceWoVAT'], $precision, ',', ' ') . ' ' . $currency;
  4051.                     $special = ($result['isDiscounted'] ? number_format($result['rawDiscountPriceWoVAT'], $precision, ',', ' ') . ' ' . $currency : false);
  4052.                     $priceInfo = $translator->trans('without VAT');
  4053.                 } else {
  4054.                     $price = number_format($result['price'], $precision, ',', ' ') . ' ' . $currency;
  4055.                     $special = ($result['isDiscounted'] ? number_format($result['special'], $precision, ',', ' ') . ' ' . $currency : false);
  4056.                     $priceInfo = '';
  4057.                 }
  4058.                 $json['products'][] = [
  4059.                     'id' => $result['product_id'],
  4060.                     'title' => $result['title'],
  4061.                     'vendor' => $result['brand'],
  4062.                     'shortDescription' => $result['description'],
  4063.                     'price' => $price,
  4064.                     'special' => $special,
  4065.                     'priceInfo' => $priceInfo,
  4066.                     'image' => $image,
  4067.                     'href' => $this->url($request)->link('product', [
  4068.                         'product_id' => $result['product_id'], 
  4069.                         'isBazaar'   => $result['isBazaar'] ?? 0
  4070.                     ]),
  4071.                     'active' => $result['active'],
  4072.                 ];
  4073.             }
  4074.             $json['popular'] = [];
  4075.             foreach ($popularLinks as $category) {
  4076.                 $json['popular'][] = [
  4077.                     'title' => $category['title'],
  4078.                     'href' => '/' . $category['link'],
  4079.                 ];
  4080.             }
  4081.         } // Not Found Product
  4082.         else {
  4083.             $json['try'] = [];
  4084.             foreach ($categories as $category) {
  4085.                 if (count($category['vendor']) == 0) {
  4086.                     $json['try'][] = [
  4087.                         'title' => $category['title'],
  4088.                         'href' => '/' . $category['link'],
  4089.                     ];
  4090.                     if (count($json['try']) >= $limit) {
  4091.                         break;
  4092.                     }
  4093.                 }
  4094.             }
  4095.         }
  4096.         // Debug
  4097.         $json['debug']['results'] = (string)$stopwatch->stop('results');
  4098.         // Recommend
  4099.         $json['recommend'] = $recommend;
  4100.         // Total
  4101.         $json['total'] = count($possibleResults);
  4102.         return new JsonResponse($json);
  4103.     }
  4104.     /**
  4105.      * @Route("/product-search", name="product_search", defaults={"_locale":""})
  4106.      * @Route("/{_locale<%supported_locales%>?}/product-search", name="product_search_locale", defaults={"_locale":""})
  4107.      * @param Request $request
  4108.      * @return Response
  4109.      * @throws \Exception
  4110.      */
  4111.     public function searchAction(Request $request): Response
  4112.     {
  4113.         $data = [];
  4114.         // Search
  4115.         if ($request->query->has('fs')) {
  4116.             $filterSearch = trim($request->query->get('fs'));
  4117.         } else {
  4118.             $filterSearch = null;
  4119.         }
  4120.         // Filter Vendor
  4121.         if ($request->query->has('fv')) {
  4122.             $filterVendor = $request->query->get('fv');
  4123.         } else {
  4124.             $filterVendor = null;
  4125.         }
  4126.         // Filter Product Type
  4127.         if ($request->query->has('ft')) {
  4128.             $filterType = $request->query->get('ft');
  4129.         } else {
  4130.             $filterType = null;
  4131.         }
  4132.         // Filter Badge
  4133.         if ($request->query->has('fb')) {
  4134.             $filterBadge = $request->query->get('fb');
  4135.         } else {
  4136.             $filterBadge = null;
  4137.         }
  4138.         // Filter Attribute
  4139.         if ($request->query->has('fa')) {
  4140.             $filterAttribute = $request->query->get('fa');
  4141.         } else {
  4142.             $filterAttribute = null;
  4143.         }
  4144.         // Filter Group OR - Create OR groups by attribute ID
  4145.         if ($request->get('fgo')) {
  4146.             $filterGroupOr = $request->get('fgo');
  4147.         } else {
  4148.             $filterGroupOr = null;
  4149.         }
  4150.         // Filter Price
  4151.         if ($request->query->has('fp')) {
  4152.             $filterPrice = explode('-', $request->query->get('fp'));
  4153.             if (!empty($filterPrice[0])) {
  4154.                 $filterPriceMin = floor((float)$filterPrice[0]);
  4155.             } else {
  4156.                 $filterPriceMin = null;
  4157.             }
  4158.             if (!empty($filterPrice[1])) {
  4159.                 $filterPriceMax = ceil((float)$filterPrice[1]);
  4160.             } else {
  4161.                 $filterPriceMax = null;
  4162.             }
  4163.         } else {
  4164.             $filterPriceMin = $filterPriceMax = null;
  4165.         }
  4166.         // Filter Discounted
  4167.         if ($request->query->has('fd')) {
  4168.             $filterDiscounted = (int)$request->query->get('fd');
  4169.         } else {
  4170.             $filterDiscounted = null;
  4171.         }
  4172.         // Filter Last Pieces
  4173.         if ($request->query->has('fl')) {
  4174.             $filterLastPieces = (int)$request->query->get('fl');
  4175.         } else {
  4176.             $filterLastPieces = null;
  4177.         }
  4178.         // Sort
  4179.         if ($request->get('sort')) {
  4180.             $sort = $request->get('sort');
  4181.         } else {
  4182.             $sort = 'price';
  4183.         }
  4184.         // Order
  4185.         if ($request->get('order')) {
  4186.             $order = $request->get('order');
  4187.         } else {
  4188.             $order = 'DESC';
  4189.         }
  4190.         // Page
  4191.         if ($request->get('page')) {
  4192.             $page = $request->get('page');
  4193.         } else {
  4194.             $page = 1;
  4195.         }
  4196.         // Limit
  4197.         if ($request->get('limit')) {
  4198.             $limit = $request->get('limit');
  4199.         } else {
  4200.             $limit = 12;
  4201.         }
  4202.         // Restore fix filters
  4203.         if ($request->query->has('_')) {
  4204.             $filterRestore = true;
  4205.         } else {
  4206.             $filterRestore = false;
  4207.         }
  4208.         // Multi-Store
  4209.         $multiStore = $this->getMultiStoreHelper($request);
  4210.         $productHelper = $this->getProductHelper($request);
  4211.         $translator = $this->getTranslator();
  4212.         $seoUrl = $this->url($request);
  4213.         $data['customerTypeId'] = $request->getSession()->get('customerTypeId');
  4214.         //-> Breadcrumbs
  4215.         $data['breadcrumbs'] = [];
  4216.         $data['breadcrumbs'][] = $this->getBreadCrumbsBase($request);
  4217.         // Breadcrumb Arguments
  4218.         $arguments = [];
  4219.         if (!is_null($filterSearch)) {
  4220.             $arguments['fs'] = $filterSearch;
  4221.         }
  4222.         if (!is_null($filterVendor)) {
  4223.             $arguments['fv'] = $filterVendor;
  4224.         }
  4225.         if (!is_null($filterType)) {
  4226.             $arguments['ft'] = $filterType;
  4227.         }
  4228.         if (!is_null($filterBadge)) {
  4229.             $arguments['fb'] = $filterBadge;
  4230.         }
  4231.         if (!is_null($filterAttribute)) {
  4232.             foreach ($filterAttribute as $key => $value) {
  4233.                 $arguments['fa[' . $key . ']'] = $value;
  4234.             }
  4235.         }
  4236.         if (!is_null($filterGroupOr)) {
  4237.             $arguments['fgo'] = $filterGroupOr;
  4238.         }
  4239.         if (!is_null($filterPriceMin) && !is_null($filterPriceMax)) {
  4240.             $arguments['fp'] = $filterPriceMin . '-' . $filterPriceMax;
  4241.         } elseif (!is_null($filterPriceMin) && is_null($filterPriceMax)) {
  4242.             $arguments['fp'] = $filterPriceMin . '-0';
  4243.         } elseif (is_null($filterPriceMin) && !is_null($filterPriceMax)) {
  4244.             $arguments['fp'] = '0-' . $filterPriceMax;
  4245.         }
  4246.         if (!is_null($filterDiscounted)) {
  4247.             $arguments['fd'] = $filterDiscounted;
  4248.         }
  4249.         if (!is_null($filterLastPieces)) {
  4250.             $arguments['fl'] = $filterLastPieces;
  4251.         }
  4252.         if ($request->get('sort')) {
  4253.             $arguments['sort'] = $sort;
  4254.         }
  4255.         if ($request->get('order')) {
  4256.             $arguments['order'] = $order;
  4257.         }
  4258.         if ($request->get('limit')) {
  4259.             $arguments['limit'] = $limit;
  4260.         }
  4261.         $data['breadcrumbs'][] = [
  4262.             'text' => $translator->trans('Search'),
  4263.             'href' => $seoUrl->link('search', $arguments),
  4264.         ];
  4265.         //<- Breadcrumbs
  4266.         // Domain
  4267.         $domain = $multiStore->getDomain();
  4268.         $data['currency'] = $domain->getCurrency();
  4269.         $data['precision'] = $domain->getPricePrecision();
  4270.         // Debug
  4271.         $data['debug'] = [];
  4272.         //-> Products
  4273.         $data['products'] = [];
  4274.         // Placeholder
  4275.         $placeholder = $this->getImage('placeholder.png', '')->resize(Image::PRODUCT_LIST_THUMB_WIDTH, Image::PRODUCT_LIST_THUMB_HEIGHT);
  4276.         // Stopwatch
  4277.         $stopwatch = new Stopwatch();
  4278.         // Entity Manager
  4279.         $entityManager = $this->getEntityManager();
  4280.         // Tokenizer
  4281.         $tokenizer = $this->getSeoUrlHelper($request);
  4282.         // Language
  4283.         $language = $domain->getLanguage();
  4284.         // Cache
  4285.         $cache = $this->cache;
  4286.         // Search Helper
  4287.         $searchHelper = new SearchHelper($entityManager, $tokenizer, $cache, $domain, $language);
  4288.         //-> Expression
  4289.         // Start Event
  4290.         $stopwatch->start('expression');
  4291.         $i = 0;
  4292.         $expressions = [];
  4293.         $expression = strtok($filterSearch, ' ');
  4294.         while ($expression !== false) {
  4295.             $expressions[] = [
  4296.                 'expression' => $expression,
  4297.                 'slug' => $tokenizer->slug($expression),
  4298.                 'mark' => 'none',
  4299.                 'priority' => (++$i),
  4300.             ];
  4301.             $expression = strtok(' ');
  4302.         }
  4303.         // Add Expression List to Helper
  4304.         $searchHelper->setExpressions($expressions);
  4305.         // Debug
  4306.         $data['debug']['expression'] = (string)$stopwatch->stop('expression');
  4307.         //<- Expression
  4308.         //-> Apply filters if there are no expressions
  4309.         // Save default filters for restore
  4310.         if (!$filterRestore) {
  4311.             $defaultFilters = [];
  4312.             if (!is_null($filterVendor)) {
  4313.                 $defaultFilters['vendor'] = $filterVendor;
  4314.             }
  4315.             if (!is_null($filterType)) {
  4316.                 $defaultFilters['productType'] = $filterType;
  4317.             }
  4318.             if (!is_null($filterBadge)) {
  4319.                 $defaultFilters['badge'] = $filterBadge;
  4320.             }
  4321.             if (!is_null($filterPriceMin)) {
  4322.                 $defaultFilters['priceMin'] = $filterPriceMin;
  4323.             }
  4324.             if (!is_null($filterPriceMax)) {
  4325.                 $defaultFilters['priceMax'] = $filterPriceMax;
  4326.             }
  4327.             if (!is_null($filterDiscounted)) {
  4328.                 $defaultFilters['discounted'] = $filterDiscounted;
  4329.             }
  4330.             if (!is_null($filterLastPieces)) {
  4331.                 $defaultFilters['lastPieces'] = $filterLastPieces;
  4332.             }
  4333.             if (!is_null($filterAttribute)) {
  4334.                 $defaultFilters['attribute'] = $filterAttribute;
  4335.             }
  4336.             $request->getSession()->set('searchDefaultFilter', $defaultFilters);
  4337.         } // Restore default filters
  4338.         else {
  4339.             $defaultFilters = $request->getSession()->get('searchDefaultFilter');
  4340.         }
  4341.         if (!$searchHelper->hasExpressions()) {
  4342.             // Filter by Vendors
  4343.             if (!empty($defaultFilters['vendor'])) {
  4344.                 $values = array_map(function ($value) {
  4345.                     return (int)$value;
  4346.                 }, explode(',', $defaultFilters['vendor']));
  4347.                 if (!empty($values)) {
  4348.                     $searchHelper->addFilter('vendor', $values);
  4349.                 }
  4350.             }
  4351.             // Filter by Product Types
  4352.             if (!empty($defaultFilters['productType'])) {
  4353.                 $values = array_map(function ($value) {
  4354.                     return (int)$value;
  4355.                 }, explode(',', $defaultFilters['productType']));
  4356.                 if (!empty($values)) {
  4357.                     $searchHelper->addFilter('productType', $values);
  4358.                 }
  4359.             }
  4360.             // Filter by Badges
  4361.             if (!empty($defaultFilters['badge'])) {
  4362.                 $values = array_map(function ($value) {
  4363.                     return (string)$value;
  4364.                 }, explode(',', $defaultFilters['badge']));
  4365.                 if (!empty($values)) {
  4366.                     $searchHelper->addFilter('badge', $values);
  4367.                 }
  4368.             }
  4369.             // Filter by Price
  4370.             if (!empty($defaultFilters['priceMin'])) {
  4371.                 $values = [(int)$defaultFilters['priceMin']];
  4372.                 if (!empty($values)) {
  4373.                     $searchHelper->addFilter('priceMin', $values);
  4374.                 }
  4375.             }
  4376.             if (!empty($defaultFilters['priceMax'])) {
  4377.                 $values = [(int)$defaultFilters['priceMax']];
  4378.                 if (!empty($values)) {
  4379.                     $searchHelper->addFilter('priceMax', $values);
  4380.                 }
  4381.             }
  4382.             // Filter discounted
  4383.             if (!empty($defaultFilters['discounted'])) {
  4384.                 $values = [1];
  4385.                 if (!empty($values)) {
  4386.                     $searchHelper->addFilter('discounted', $values);
  4387.                 }
  4388.             }
  4389.             // Filter last pieces
  4390.             if (!empty($defaultFilters['lastPieces'])) {
  4391.                 $values = [1];
  4392.                 if (!empty($values)) {
  4393.                     $searchHelper->addFilter('lastPieces', $values);
  4394.                 }
  4395.             }
  4396.             // Filter by Attribute
  4397.             if (!empty($defaultFilters['attribute'])) {
  4398.                 foreach ($defaultFilters['attribute'] as $attributeId => $values) {
  4399.                     $values = array_map(function ($value) {
  4400.                         return (int)$value;
  4401.                     }, explode(',', $values));
  4402.                     if (!empty($values)) {
  4403.                         $searchHelper->addFilter('attribute_' . $attributeId, $values);
  4404.                     }
  4405.                 }
  4406.             }
  4407.         }
  4408.         //<- Apply filters if there are no expressions
  4409.         //-> Initialize Search
  4410.         // Start Debug Event
  4411.         $stopwatch->start('initialize');
  4412.         $searchHelper->initialize();
  4413.         // Debug
  4414.         $json['debug']['initialize'] = (string)$stopwatch->stop('initialize');
  4415.         //<- Initialize Search
  4416.         // Vendors
  4417.         $vendors = $searchHelper->getVendors();
  4418.         // Product Types
  4419.         $productTypes = $searchHelper->getProductTypes();
  4420.         // Products
  4421.         $products = $searchHelper->getProducts();
  4422.         //-> Search
  4423.         // Start Event
  4424.         $stopwatch->start('search');
  4425.         $search = $searchHelper->search();
  4426.         // Debug
  4427.         $data['debug']['search'] = (string)$stopwatch->stop('search');
  4428.         //<- Search
  4429.         //-> Collection of possible results
  4430.         // Start Event
  4431.         $stopwatch->start('possible-result');
  4432.         // Possible Results
  4433.         $possibleResults = $searchHelper->possibleResults($search);
  4434.         // Attributes
  4435.         $attributes = $searchHelper->getAttributes($possibleResults);
  4436.         //-> Filter Possible Results
  4437.         $filteredPossibleResults = $possibleResults;
  4438.         // Selected Vendors
  4439.         if (!empty($filterVendor)) {
  4440.             $selectedVendors = array_map(function ($value) {
  4441.                 return (int)$value;
  4442.             }, explode(',', $filterVendor));
  4443.         }
  4444.         // Selected Product Types
  4445.         if (!empty($filterType)) {
  4446.             $selectedProductTypes = array_map(function ($value) {
  4447.                 return (int)$value;
  4448.             }, explode(',', $filterType));
  4449.         }
  4450.         foreach ($filteredPossibleResults as $key => $result) {
  4451.             if (!empty($products['all'][$result['id']])) {
  4452.                 $product = $products['all'][$result['id']];
  4453.                 if (!empty($selectedVendors) && !in_array((int)$product['vendor_id'], $selectedVendors)) {
  4454.                     unset($filteredPossibleResults[$key]);
  4455.                     continue;
  4456.                 } elseif (!empty($selectedProductTypes) && !in_array((int)$product['type_id'], $selectedProductTypes)) {
  4457.                     unset($filteredPossibleResults[$key]);
  4458.                     continue;
  4459.                 }
  4460.                 if ($request->query->has('fl') && $request->query->get('fl') == 1 && (int)$product['available'] > 1) {
  4461.                     unset($filteredPossibleResults[$key]);
  4462.                     continue;
  4463.                 }
  4464.                 if ($request->query->has('fd') && $request->query->get('fd') == 1 && (int)$product['discounted'] != 1) {
  4465.                     unset($filteredPossibleResults[$key]);
  4466.                     continue;
  4467.                 }
  4468.                 if (!is_null($filterPriceMin) || !is_null($filterPriceMax)) {
  4469.                     if ($domain->getType() == Domain::TYPE_RETAIL) {
  4470.                         if ((int)$product['discounted'] == 1) {
  4471.                             $price = (float)$product['discount'] * (1 + ((int)$domain->getVat()) / 100);
  4472.                         } else {
  4473.                             $price = (float)$product['price'] * (1 + ((int)$domain->getVat()) / 100);
  4474.                         }
  4475.                     } else {
  4476.                         if ((int)$product['discounted'] == 1) {
  4477.                             $price = (float)$product['discount'];
  4478.                         } else {
  4479.                             $price = (float)$product['price'];
  4480.                         }
  4481.                     }
  4482.                     if (!is_null($filterPriceMin) && !is_null($filterPriceMax) && !($price >= $filterPriceMin && $price <= $filterPriceMax)) {
  4483.                         unset($filteredPossibleResults[$key]);
  4484.                         continue;
  4485.                     } elseif (!is_null($filterPriceMin) && is_null($filterPriceMax) && !($price >= $filterPriceMin)) {
  4486.                         unset($filteredPossibleResults[$key]);
  4487.                         continue;
  4488.                     } elseif (is_null($filterPriceMin) && !is_null($filterPriceMax) && !($price <= $filterPriceMax)) {
  4489.                         unset($filteredPossibleResults[$key]);
  4490.                         continue;
  4491.                     }
  4492.                 }
  4493.                 if ($request->query->has('fa')) {
  4494.                     foreach ($request->query->get('fa') as $attributeId => $filters) {
  4495.                         $skip = true;
  4496.                         if (!empty($attributes[$attributeId]['options'])) {
  4497.                             $selectedOptions = explode(',', $filters);
  4498.                             foreach ($selectedOptions as $selectedOptionId) {
  4499.                                 if (!empty($attributes[$attributeId]['options'][(int)$selectedOptionId]['products']) && in_array((int)$product['id'], $attributes[$attributeId]['options'][(int)$selectedOptionId]['products'])) {
  4500.                                     $skip = false;
  4501.                                 }
  4502.                             }
  4503.                         }
  4504.                         if ($skip) {
  4505.                             unset($filteredPossibleResults[$key]);
  4506.                             continue 2;
  4507.                         }
  4508.                     }
  4509.                 }
  4510.             }
  4511.         }
  4512.         //<- Filter Possible Results
  4513.         // Custom Sort
  4514.         if ($request->query->has('sort') && $request->query->get('sort') != 'default') {
  4515.             $sortOrderPriority = [];
  4516.             $sortOrderCustom = [];
  4517.             $flagCustom = SORT_STRING;
  4518.             switch ($sort) {
  4519.                 case 'name':
  4520.                     foreach ($filteredPossibleResults as $key => $result) {
  4521.                         // ProductId
  4522.                         $productId = (int)$result['id'];
  4523.                         // Product Details
  4524.                         if (!empty($products['all'][$productId])) {
  4525.                             $product = $products['all'][$productId];
  4526.                             // Vendor
  4527.                             $vendor = '';
  4528.                             if (!empty($vendors[$product['vendor_id']]['name'])) {
  4529.                                 $vendor = $vendors[$product['vendor_id']]['name'] . ' ';
  4530.                             }
  4531.                             $sortOrderCustom[$key] = $vendor . $product['name'];
  4532.                         }
  4533.                         $sortOrderPriority[$key] = $result['priority'];
  4534.                     }
  4535.                     $flagCustom = SORT_STRING;
  4536.                     break;
  4537.                 case 'price':
  4538.                     foreach ($filteredPossibleResults as $key => $result) {
  4539.                         // ProductId
  4540.                         $productId = (int)$result['id'];
  4541.                         // Product Details
  4542.                         if (!empty($products['all'][$productId])) {
  4543.                             $product = $products['all'][$productId];
  4544.                             if ((int)$product['discounted'] == 1) {
  4545.                                 $sortOrderCustom[$key] = (float)$product['discount'];
  4546.                             } else {
  4547.                                 $sortOrderCustom[$key] = (float)$product['price'];
  4548.                             }
  4549.                         }
  4550.                         $sortOrderPriority[$key] = $result['priority'];
  4551.                     }
  4552.                     $flagCustom = SORT_NUMERIC;
  4553.                     break;
  4554.             }
  4555.             if (strtoupper($order) == 'DESC') {
  4556.                 array_multisort($sortOrderCustom, SORT_DESC, $flagCustom, $sortOrderPriority, SORT_DESC, SORT_NUMERIC, $filteredPossibleResults);
  4557.             } else {
  4558.                 array_multisort($sortOrderCustom, SORT_ASC, $flagCustom, $sortOrderPriority, SORT_DESC, SORT_NUMERIC, $filteredPossibleResults);
  4559.             }
  4560.         }
  4561.         // Offset
  4562.         $offset = ($page - 1) * $limit;
  4563.         // Found Products
  4564.         $foundProducts = array_map(function ($product) {
  4565.             return (int)$product['id'];
  4566.         }, array_slice($filteredPossibleResults, $offset, $limit));
  4567.         // Debug
  4568.         $data['debug']['possible-result'] = (string)$stopwatch->stop('possible-result');
  4569.         //<- Collection of possible results
  4570.         // Results
  4571.         if (!empty($foundProducts)) {
  4572.             $_results = $productHelper->getStructuredDataForProductsById($foundProducts, 'list');
  4573.             // Re-sort results
  4574.             $results = [];
  4575.             foreach ($foundProducts as $productId) {
  4576.                 $results[] = $_results[$productId];
  4577.             }
  4578.         }
  4579.         //-> Filters
  4580.         $data['productTypes'] = $data['vendors'] = [];
  4581.         $data['priceMin'] = $data['priceMax'] = false;
  4582.         foreach ($possibleResults as $possibleResult) {
  4583.             if (!empty($products['all'][$possibleResult['id']])) {
  4584.                 // Product
  4585.                 $product = $products['all'][$possibleResult['id']];
  4586.                 // Product Type
  4587.                 if (!empty($productTypes[$product['type_id']])) {
  4588.                     $data['productTypes'][$product['type_id']] = [
  4589.                         'id' => $productTypes[$product['type_id']]['id'],
  4590.                         'name' => $productTypes[$product['type_id']]['name'],
  4591.                     ];
  4592.                 }
  4593.                 // Vendor
  4594.                 if (!empty($vendors[$product['vendor_id']])) {
  4595.                     $data['vendors'][$product['vendor_id']] = [
  4596.                         'id' => $vendors[$product['vendor_id']]['id'],
  4597.                         'name' => $vendors[$product['vendor_id']]['name'],
  4598.                     ];
  4599.                 }
  4600.                 // Price
  4601.                 if ((int)$product['discounted'] == 1) {
  4602.                     $price = (float)$product['discount'];
  4603.                 } else {
  4604.                     $price = (float)$product['price'];
  4605.                 }
  4606.                 if ($data['priceMin'] === false || $data['priceMax'] === false) {
  4607.                     $data['priceMin'] = $data['priceMax'] = $price;
  4608.                 }
  4609.                 if ($data['priceMin'] > $price) {
  4610.                     $data['priceMin'] = $price;
  4611.                 }
  4612.                 if ($data['priceMax'] < $price) {
  4613.                     $data['priceMax'] = $price;
  4614.                 }
  4615.             }
  4616.         }
  4617.         if (!empty($data['productTypes'])) {
  4618.             $sortOrder = [];
  4619.             foreach ($data['productTypes'] as $key => $value) {
  4620.                 $sortOrder[$key] = $value['name'];
  4621.             }
  4622.             array_multisort($sortOrder, SORT_ASC, SORT_STRING, $data['productTypes']);
  4623.         }
  4624.         if (!empty($data['vendors'])) {
  4625.             $sortOrder = [];
  4626.             foreach ($data['vendors'] as $key => $value) {
  4627.                 $sortOrder[$key] = $value['name'];
  4628.             }
  4629.             array_multisort($sortOrder, SORT_ASC, SORT_STRING, $data['vendors']);
  4630.         }
  4631.         // Qaulity
  4632.         $data['qualityStatuses'] = [];
  4633.         if (!empty($attributes[Attribute::ATTRIBUTE_ID_QUALITY]['options'])) {
  4634.             foreach ($attributes[Attribute::ATTRIBUTE_ID_QUALITY]['options'] as $attributeOptionId => $attributeOption) {
  4635.                 $data['qualityStatuses'][] = [
  4636.                     'id' => $attributeOptionId,
  4637.                     'index' => $attributeOption['index'],
  4638.                     'title' => $attributeOption['title'],
  4639.                 ];
  4640.             }
  4641.             $qualityOrder = [
  4642.                 AttributeOption::ATTRIBUTE_OPTION_QUALITY_GOLD,
  4643.                 AttributeOption::ATTRIBUTE_OPTION_QUALITY_SILVER,
  4644.                 AttributeOption::ATTRIBUTE_OPTION_QUALITY_BRONZ,
  4645.                 AttributeOption::ATTRIBUTE_OPTION_QUALITY_NEW,
  4646.                 AttributeOption::ATTRIBUTE_OPTION_QUALITY_BAZAAR
  4647.             ];
  4648.             $sortOrder = [];
  4649.             foreach ($data['qualityStatuses'] as $key => $value) {
  4650.                 $position = array_search($value['id'], $qualityOrder);
  4651.                 $sortOrder[$key] = $position === false ? count($qualityOrder) : $position;
  4652.             }
  4653.             array_multisort($sortOrder, SORT_ASC, $data['qualityStatuses']);
  4654.         }
  4655.         // Attribute Filters
  4656.         $data['attributeFilters'] = [];
  4657.         if (empty($selectedProductTypes) && !empty($data['productTypes']) && count($data['productTypes']) == 1) {
  4658.             $productType = array_shift($data['productTypes']);
  4659.             $selectedProductTypes = [$productType['id']];
  4660.         }
  4661.         if (!empty($selectedProductTypes)) {
  4662.             $selectedProductType = array_shift($selectedProductTypes);
  4663.             if (in_array($selectedProductType, [ProductType::PRODUCT_TYPE_ID_NOTEBOOK, ProductType::PRODUCT_TYPE_ID_PC, ProductType::PRODUCT_TYPE_ID_MONITOR, ProductType::PRODUCT_TYPE_ID_SMARTPHONE, ProductType::PRODUCT_TYPE_ID_SMARTWATCH, ProductType::PRODUCT_TYPE_ID_TABLET])) {
  4664.                 $attributeFilters = $searchHelper->getAttributeFiltersByProductType($selectedProductType);
  4665.                 foreach ($attributeFilters as $attributeId) {
  4666.                     // Skip Default Filters
  4667.                     if (isset($defaultFilters['attribute'][$attributeId])) {
  4668.                         continue;
  4669.                     }
  4670.                     // Skip Quality Filter
  4671.                     if ($attributeId == Attribute::ATTRIBUTE_ID_QUALITY) {
  4672.                         continue;
  4673.                     }
  4674.                     if (!empty($attributes[$attributeId]['options']) && count($attributes[$attributeId]['options']) > 1) {
  4675.                         $data['attributeFilters'][$attributeId] = [
  4676.                             'id' => $attributeId,
  4677.                             'title' => $attributes[$attributeId]['title'],
  4678.                             'options' => [],
  4679.                         ];
  4680.                         foreach ($attributes[$attributeId]['options'] as $attributeOptionId => $attributeOption) {
  4681.                             $data['attributeFilters'][$attributeId]['options'][] = [
  4682.                                 'id' => $attributeOptionId,
  4683.                                 'index' => $attributeOption['index'],
  4684.                                 'title' => $attributeOption['title'],
  4685.                             ];
  4686.                         }
  4687.                         $sortOrder = [];
  4688.                         $sortType = SORT_STRING;
  4689.                         foreach ($data['attributeFilters'][$attributeId]['options'] as $key => $value) {
  4690.                             if (in_array($attributeId, [1, 12, 25, 45, 46, 63, 68, 141])) {
  4691.                                 $sortOrder[$key] = $value['title'];
  4692.                             } else {
  4693.                                 $sortOrder[$key] = $value['index'];
  4694.                                 $sortType = SORT_NUMERIC;
  4695.                             }
  4696.                         }
  4697.                         array_multisort($sortOrder, SORT_DESC, $sortType, $data['attributeFilters'][$attributeId]['options']);
  4698.                     }
  4699.                 }
  4700.             }
  4701.         }
  4702.         // Price
  4703.         if ($multiStore->getBasePrice() != MultiStore::BASE_PRICE_NET) {
  4704.             $data['priceMin'] = $data['priceMin'] * (1 + ($domain->getVat() / 100));
  4705.             $data['priceMax'] = $data['priceMax'] * (1 + ($domain->getVat() / 100));
  4706.         }
  4707.         //<- Filters
  4708.         // Results
  4709.         if (!empty($results)) {
  4710.             foreach ($results as $result) {
  4711.                 $image = $placeholder;
  4712.                 if (is_object($result['images'])) {
  4713.                     $image = $this->getImage($result['images'], 'product/' . $result['code'])->resize(Image::PRODUCT_LIST_THUMB_WIDTH, Image::PRODUCT_LIST_THUMB_HEIGHT);
  4714.                 }
  4715.                 $data['products'][] = [
  4716.                     'id' => $result['id'],
  4717.                     'title' => sprintf('%s - %s', $result['title'], $result['code']),
  4718.                     'vendor' => $result['vendor'],
  4719.                     'labels' => $result['badges'],
  4720.                     'price' => $result['vatPrice'],
  4721.                     'special' => ($result['isDiscounted'] ? $result['discountVatPrice'] : false),
  4722.                     'rawPrice' => $result['rawPrice'],
  4723.                     'rawDiscountPrice' => $result['rawDiscountPrice'],
  4724.                     'image' => $image,
  4725.                     'attributes' => $result['attributes'],
  4726.                     'attributesListTxt' => $result['attributesListTxt'],
  4727.                     'available' => $result['availableQty'],
  4728.                     'href' => $seoUrl->link('product', [
  4729.                         'product_id' => $result['id'], 
  4730.                         'isBazaar'   => $result['isBazaar'] ?? 0
  4731.                     ]),
  4732.                     'active' => $result['active'],
  4733.                     'timedSalesActive' => $result['timedSalesActive'],
  4734.                     'reviewCount' => $result['reviewCount'],
  4735.                     'reviewStars' => $result['reviewStars'],
  4736.                     'reviews' => $result['reviews'],
  4737.                     'typeId' => $result['productTypeId'],
  4738.                     'warrantyYear' => $this->getWarrantyForProductType($domain->getId(), $result['productTypeId'])['year'],
  4739.                     'labelOS' => $this->getProductHelper($request)->getOSLabel($result),
  4740.                     'isBestseller' => $result['isBestseller']
  4741.                 ];
  4742.             }
  4743.         } else {
  4744.             $data['mainProducts'] = [];
  4745.             $productHelper = $this->getProductHelper($request);
  4746.             // Main Products based on homepage
  4747.             $mainProductsCacheKey = 'search.main.products.v1.' . $domain->getId() . '.' . $language->getCode();
  4748.             $mainProductsCacheItem = $cache->getItem($mainProductsCacheKey);
  4749.             if ($mainProductsCacheItem->isHit()) {
  4750.                 $data['mainProducts'] = $mainProductsCacheItem->get();
  4751.             } else {
  4752.                 $productGroupProductData = $productHelper->getProductGroupProducts('homepage.main', $domain);
  4753.                 $productGroupProducts = $productGroupProductData['productGroupProducts'];
  4754.                 $groupProductCodesAdded = $productGroupProductData['productGroupCodesAdded'];
  4755.                 $productsToDisplay = $productGroupProductData['productsToDisplay'];
  4756.                 $productGroupResults = $productHelper->getStructuredDataForProducts($productGroupProducts);
  4757.                 $data['mainProducts'] = $productHelper->convertStructuredDataToListViewData($this->url($request), $productGroupResults, $placeholder);
  4758.                 // Fill in
  4759.                 if (count($groupProductCodesAdded) < $productsToDisplay) {
  4760.                     $maxResults = $productsToDisplay - count($groupProductCodesAdded);
  4761.                     // Already Added
  4762.                     $productAlreadyAddedWhere = '';
  4763.                     if (count($groupProductCodesAdded) > 0) {
  4764.                         $productAlreadyAddedWhere = ' AND p.code NOT IN (' . implode(',', $groupProductCodesAdded) . ')';
  4765.                     }
  4766.                     $retailPage = $domain->getType() == 'retail';
  4767.                     $notebookSaleProducts = $entityManager->createQuery("SELECT p
  4768.                         FROM AtechNetCoreBundle:Product p
  4769.                         LEFT JOIN AtechNetCoreBundle:ProductMeta pm WITH pm.id = (
  4770.                             SELECT pm2.id FROM AtechNetCoreBundle:ProductMeta pm2 WHERE pm2.product = p.id AND pm2.domain = " . $domain->getId() . "
  4771.                         )
  4772.                         WHERE p.type = 52 AND pm.discounted = 1 AND pm.active = 1 AND p.available > 0 AND pm.orderable = 1 AND pm.listed = 1" . ($retailPage ? " AND p.qualityStatus != 9" : "") . $productAlreadyAddedWhere . "
  4773.                         ORDER BY pm.currentVatPrice ASC, p.updated DESC")
  4774.                         ->setMaxResults($maxResults)
  4775.                         ->getResult()
  4776.                     ;
  4777.                     $results = $productHelper->getStructuredDataForProducts($notebookSaleProducts);
  4778.                     $data['mainProducts'] = array_merge($data['mainProducts'], $this->getProductHelper($request)->convertStructuredDataToListViewData($this->url($request), $results, $placeholder));
  4779.                 }
  4780.                 foreach ($data['mainProducts'] as $key => $value) {
  4781.                     $data['mainProducts'][$key]['warrantyYear'] = $value['qualityStatusId'] == Product::QualityStatus_Bazaar ? 1 : $this->getWarrantyForProductType($domain->getId(), $value['typeId'])['year'];
  4782.                 }
  4783.                 $mainProductsCacheItem->set($data['mainProducts']);
  4784.                 $mainProductsCacheItem->expiresAfter(self::CACHE_LIFETIME_15_MINUTES);
  4785.                 $cache->save($mainProductsCacheItem);
  4786.             }
  4787.         }
  4788.         //<- Products
  4789.         //-> Pagination
  4790.         if (!empty($results)) {
  4791.             // Arguments
  4792.             $arguments = [];
  4793.             if (!is_null($filterSearch)) {
  4794.                 $arguments['fs'] = $filterSearch;
  4795.             }
  4796.             if ($request->query->has('fv')) {
  4797.                 $arguments['fv'] = $filterVendor;
  4798.             }
  4799.             if ($request->query->has('ft')) {
  4800.                 $arguments['ft'] = $filterType;
  4801.             }
  4802.             if (!is_null($filterBadge)) {
  4803.                 $arguments['fb'] = $filterBadge;
  4804.             }
  4805.             if (!is_null($filterAttribute)) {
  4806.                 foreach ($filterAttribute as $key => $value) {
  4807.                     $arguments['fa[' . $key . ']'] = $value;
  4808.                 }
  4809.             }
  4810.             if (!is_null($filterGroupOr)) {
  4811.                 $arguments['fgo'] = $filterGroupOr;
  4812.             }
  4813.             if (!is_null($filterPriceMin) && !is_null($filterPriceMax)) {
  4814.                 $arguments['fp'] = $filterPriceMin . '-' . $filterPriceMax;
  4815.             } elseif (!is_null($filterPriceMin) && is_null($filterPriceMax)) {
  4816.                 $arguments['fp'] = $filterPriceMin . '-0';
  4817.             } elseif (is_null($filterPriceMin) && !is_null($filterPriceMax)) {
  4818.                 $arguments['fp'] = '0-' . $filterPriceMax;
  4819.             }
  4820.             if (!is_null($filterDiscounted)) {
  4821.                 $arguments['fd'] = $filterDiscounted;
  4822.             }
  4823.             if (!is_null($filterLastPieces)) {
  4824.                 $arguments['fl'] = $filterLastPieces;
  4825.             }
  4826.             if ($request->get('sort')) {
  4827.                 $arguments['sort'] = $sort;
  4828.             }
  4829.             if ($request->get('order')) {
  4830.                 $arguments['order'] = $order;
  4831.             }
  4832.             if ($request->get('limit')) {
  4833.                 $arguments['limit'] = $limit;
  4834.             }
  4835.             if ($filterRestore) {
  4836.                 $arguments['_'] = '1';
  4837.             }
  4838.             $arguments['page'] = '{page}';
  4839.             $data['pagination'] = [
  4840.                 'total' => count($filteredPossibleResults),
  4841.                 'page' => $page,
  4842.                 'limit' => $limit,
  4843.                 'moreButton' => true,
  4844.                 'url' => urldecode($seoUrl->link('search', $arguments)),
  4845.             ];
  4846.         } else {
  4847.             $data['pagination'] = [];
  4848.         }
  4849.         //<- Pagination
  4850.         // Filter Values
  4851.         if (!is_null($filterSearch)) {
  4852.             $data['filterSearch'] = $filterSearch;
  4853.         } else {
  4854.             $data['filterSearch'] = '';
  4855.         }
  4856.         if (!is_null($filterVendor)) {
  4857.             $data['filterVendor'] = explode(',', $filterVendor);
  4858.         } else {
  4859.             $data['filterVendor'] = [];
  4860.         }
  4861.         if (!is_null($filterType)) {
  4862.             $data['filterType'] = explode(',', $filterType);
  4863.         } else {
  4864.             $data['filterType'] = [];
  4865.         }
  4866.         if (!is_null($filterBadge)) {
  4867.             $data['filterBadge'] = explode(',', $filterBadge);
  4868.         } else {
  4869.             $data['filterBadge'] = [];
  4870.         }
  4871.         if (!is_null($filterAttribute)) {
  4872.             $data['filterAttribute'] = $data['filterAttributes'] = [];
  4873.             foreach ($filterAttribute as $attributeId => $attribute) {
  4874.                 $options = explode(',', $attribute);
  4875.                 foreach ($options as $option) {
  4876.                     array_push($data['filterAttribute'], $option);
  4877.                 }
  4878.                 if ($attributeId !== 101) {
  4879.                     $data['filterAttributes'][$attributeId] = $attribute;
  4880.                 }
  4881.             }
  4882.         } else {
  4883.             $data['filterAttribute'] = $data['filterAttributes'] = [];
  4884.         }
  4885.         if (!is_null($filterGroupOr)) {
  4886.             $data['filterGroupOr'] = explode(',', $filterGroupOr);
  4887.         } else {
  4888.             $data['filterGroupOr'] = [];
  4889.         }
  4890.         if (!is_null($filterPriceMin)) {
  4891.             $data['filterPriceMin'] = $filterPriceMin;
  4892.         } else {
  4893.             $data['filterPriceMin'] = false;
  4894.         }
  4895.         if (!is_null($filterPriceMax)) {
  4896.             $data['filterPriceMax'] = $filterPriceMax;
  4897.         } else {
  4898.             $data['filterPriceMax'] = false;
  4899.         }
  4900.         if (!is_null($filterDiscounted)) {
  4901.             $data['filterDiscounted'] = $filterDiscounted;
  4902.         } else {
  4903.             $data['filterDiscounted'] = false;
  4904.         }
  4905.         if (!is_null($filterLastPieces)) {
  4906.             $data['filterLastPieces'] = $filterLastPieces;
  4907.         } else {
  4908.             $data['filterLastPieces'] = false;
  4909.         }
  4910.         $data['defaultFilters'] = $defaultFilters;
  4911.         // Sort By
  4912.         $data['sortOrders'] = [];
  4913.         $data['sortOrders'][] = [
  4914.             'text' => $translator->trans('Sort by') . ': ' . $translator->trans('Default'),
  4915.             'value' => 'default-asc',
  4916.             'sort' => 'default',
  4917.             'order' => 'asc',
  4918.         ];
  4919.         $data['sortOrders'][] = [
  4920.             'text' => $translator->trans('Sort by') . ': ' . $translator->trans('Name') . ' (' . $translator->trans('A to Z') . ')',
  4921.             'value' => 'name-asc',
  4922.             'sort' => 'name',
  4923.             'order' => 'asc',
  4924.         ];
  4925.         $data['sortOrders'][] = [
  4926.             'text' => $translator->trans('Sort by') . ': ' . $translator->trans('Name') . ' (' . $translator->trans('Z to A') . ')',
  4927.             'value' => 'name-desc',
  4928.             'sort' => 'name',
  4929.             'order' => 'desc',
  4930.         ];
  4931.         $data['sortOrders'][] = [
  4932.             'text' => $translator->trans('Sort by') . ': ' . $translator->trans('Price') . ' (' . $translator->trans('low to high') . ')',
  4933.             'value' => 'price-asc',
  4934.             'sort' => 'price',
  4935.             'order' => 'asc',
  4936.         ];
  4937.         $data['sortOrders'][] = [
  4938.             'text' => $translator->trans('Sort by') . ': ' . $translator->trans('Price') . ' (' . $translator->trans('high to low') . ')',
  4939.             'value' => 'price-desc',
  4940.             'sort' => 'price',
  4941.             'order' => 'desc',
  4942.         ];
  4943.         $data['sort'] = $sort;
  4944.         $data['order'] = $order;
  4945.         // Limit
  4946.         $data['limits'] = [];
  4947.         $limits = [12, 24, 48, 96];
  4948.         foreach ($limits as $value) {
  4949.             $data['limits'][] = [
  4950.                 'text' => $value,
  4951.                 'value' => $value,
  4952.             ];
  4953.         }
  4954.         $data['limit'] = $limit;
  4955.         $data['salesManager'] = [];
  4956.         if ($data['customerTypeId'] == MultiStore::CUSTOMER_TYPE_WHOLESALE) {
  4957.             $loggedInCustomer = $this->getLoginHelper($request)->getLoggedInCustomer();
  4958.             $salesManager = $loggedInCustomer->getSalesManager();
  4959.             $data['salesManager']['name'] = '';
  4960.             $data['salesManager']['username'] = '';
  4961.             if ($salesManager) {
  4962.                 $data['salesManager']['name'] = $salesManager->getFirstName();
  4963.                 $data['salesManager']['username'] = $salesManager->getUsername();
  4964.                 $data['salesManager']['phone'] = $salesManager->getPhone();
  4965.             }
  4966.         }
  4967.         $data['webshop_phone_number'] = $this->getContactInfos()['phone.webshop.' . $domain->getLanguage()->getCode() . '.' . $domain->getType()];
  4968.         $data['header'] = $this->getHeader($request);
  4969.         $data['footer'] = $this->getFooter($request);
  4970.         $data['contentBottom'] = $this->getContentBottom($request);
  4971.         return $this->render('AtechNetCoreBundle/Product/search.html.twig', $data);
  4972.     }
  4973.     /**
  4974.      * @Route("/product/log/search", name="product_log_search", methods = {"POST"}, defaults={"_locale":""})
  4975.      * @Route("/{_locale<%supported_locales%>?}/product/log/search", name="product_log_search_locale", methods = {"POST"}, defaults={"_locale":""})
  4976.      * @param Request $request
  4977.      * @return JsonResponse
  4978.      */
  4979.     public function logSearchAction(Request $request): JsonResponse
  4980.     {
  4981.         // JSON
  4982.         $json = [];
  4983.         return new JsonResponse($json);
  4984.         if ($this->getEnvironment() == 'prod') {
  4985.             \Sentry\configureScope(function (\Sentry\State\Scope $scope): void {
  4986.                 $scope->setUser([
  4987.                     'ip_address' => $_SERVER['REMOTE_ADDR'],
  4988.                 ]);
  4989.             });
  4990.         }
  4991.         // Stopwatch
  4992.         $stopwatch = new Stopwatch();
  4993.         // Debug
  4994.         $stopwatch->start('log');
  4995.         // Search Term
  4996.         if ($request->get('keyword')) {
  4997.             $keyword = urldecode(trim($request->get('keyword')));
  4998.         } else {
  4999.             $keyword = null;
  5000.         }
  5001.         // Entity Manager
  5002.         $entityManager = $this->getEntityManager();
  5003.         // Connection
  5004.         $connection = $entityManager->getConnection();
  5005.         // Multi-Store
  5006.         $multiStore = $this->getMultiStoreHelper($request);
  5007.         // Statistics Entry
  5008.         if (!empty($keyword)) {
  5009.             // Customer
  5010.             $customerId = null;
  5011.             if ($this->getLoginHelper($request)->isLoggedIn()) {
  5012.                 $customerId = $this->getLoginHelper($request)->getLoggedInCustomerId();
  5013.             }
  5014.             //-> Action
  5015.             $action = [];
  5016.             if ($request->get('event')) {
  5017.                 $action['event'] = $request->get('event');
  5018.             }
  5019.             if ($request->get('location')) {
  5020.                 $action['location'] = $request->get('location');
  5021.             }
  5022.             if (!empty($request->get('page'))) {
  5023.                 $action['page'] = (int)$request->get('page');
  5024.             }
  5025.             // Convert
  5026.             if (!empty($action)) {
  5027.                 $action = json_encode($action);
  5028.             } else {
  5029.                 $action = null;
  5030.             }
  5031.             //<- Action
  5032.             //-> Payload
  5033.             $payload = [];
  5034.             if ($request->get('deviceType')) {
  5035.                 $payload['deviceType'] = $request->get('deviceType');
  5036.             }
  5037.             if ($request->get('screenWidth')) {
  5038.                 $payload['screenWidth'] = $request->get('screenWidth');
  5039.             }
  5040.             if ($request->get('screenHeight')) {
  5041.                 $payload['screenHeight'] = $request->get('screenHeight');
  5042.             }
  5043.             if ($request->get('screenOrientation')) {
  5044.                 $payload['screenOrientation'] = $request->get('screenOrientation');
  5045.             }
  5046.             if ($request->getClientIp()) {
  5047.                 $payload['ip'] = $request->getClientIp();
  5048.             }
  5049.             // Convert
  5050.             if (!empty($payload)) {
  5051.                 $payload = json_encode($payload);
  5052.             } else {
  5053.                 $payload = null;
  5054.             }
  5055.             //<- Payload
  5056.             //-> Content
  5057.             $content = [];
  5058.             if ($request->get('total')) {
  5059.                 $content['result'] = json_decode($request->get('total'), true);
  5060.             }
  5061.             if ($request->get('content')) {
  5062.                 $content['result'] = json_decode($request->get('content'), true);
  5063.             }
  5064.             if ($request->get('product')) {
  5065.                 $content['highlighted'] = json_decode($request->get('product'), true);
  5066.             }
  5067.             if (!empty($request->get('select'))) {
  5068.                 $content['select'] = $request->get('select');
  5069.             }
  5070.             // Convert
  5071.             if (!empty($content)) {
  5072.                 $content = json_encode($content);
  5073.             } else {
  5074.                 $content = null;
  5075.             }
  5076.             //<- Content
  5077.             // Prevent double log
  5078.             $log = true;
  5079.             if ($request->getSession()->has('searchLog')) {
  5080.                 $searchLog = $request->getSession()->get('searchLog');
  5081.                 if (time() < strtotime('-1 minute', $searchLog['t']) && trim($searchLog['k']) == trim($keyword)) {
  5082.                     if (!empty($action['event'])) {
  5083.                         $e = $action['event'];
  5084.                     } else {
  5085.                         $e = '-';
  5086.                     }
  5087.                     if (!empty($action['location'])) {
  5088.                         $l = $action['location'];
  5089.                     } else {
  5090.                         $l = '-';
  5091.                     }
  5092.                     if (!empty($action['page'])) {
  5093.                         $p = $action['page'];
  5094.                     } else {
  5095.                         $p = '-';
  5096.                     }
  5097.                     if ($e == $searchLog['e'] && $l == $searchLog['l'] && $p == $searchLog['p']) {
  5098.                         $log = false;
  5099.                     }
  5100.                 }
  5101.             }
  5102.             if ($log) {
  5103.                 // Statement
  5104.                 $statistics = $connection->prepare("INSERT INTO statistics_search SET domain_id = :domainId, session_id = :sessionId, customer_id = :customerId, keyword = :keyword, `action` = :action, content = :content, payload = :payload, created = NOW()");
  5105.                 // Save
  5106.                 $statistics->execute([
  5107.                     'domainId' => $multiStore->getDomainId(),
  5108.                     'sessionId' => $request->getSession()->getId(),
  5109.                     'customerId' => $customerId,
  5110.                     'keyword' => $keyword,
  5111.                     'action' => $action,
  5112.                     'content' => $content,
  5113.                     'payload' => $payload,
  5114.                 ]);
  5115.                 $request->getSession()->set('searchLog', [
  5116.                     't' => time(),
  5117.                     'k' => $keyword,
  5118.                     'e' => (!empty($action['event']) ? $action['event'] : '-'),
  5119.                     'l' => (!empty($action['location']) ? $action['location'] : '-'),
  5120.                     'p' => (!empty($action['page']) ? $action['page'] : '-'),
  5121.                 ]);
  5122.             }
  5123.         }
  5124.         // Debug
  5125.         $json['debug'] = (string)$stopwatch->stop('log');
  5126.         // Response
  5127.         return new JsonResponse($json);
  5128.     }
  5129.     /**
  5130.      * @Route("/akciove-produkty",                                 name="product_all_discount_sk", defaults={"_locale":""})
  5131.      * @Route("/{_locale<%supported_locales%>?}/akciove-produkty", name="product_all_discount_sk_locale", defaults={"_locale":""})
  5132.      * @Route("/akcios-termekek",                                  name="product_all_discount_hu", defaults={"_locale":""})
  5133.      * @Route("/{_locale<%supported_locales%>?}/akcios-termekek",  name="product_all_discount_hu_locale", defaults={"_locale":""})
  5134.      * @param Request $request
  5135.      * @return mixed
  5136.      */
  5137.     public function allDiscountProductsAction(Request $request)
  5138.     {
  5139.         if ($this->getEnvironment() == 'prod') {
  5140.             \Sentry\configureScope(function (\Sentry\State\Scope $scope): void {
  5141.                 $scope->setUser([
  5142.                     'ip_address' => $_SERVER['REMOTE_ADDR'],
  5143.                 ]);
  5144.             });
  5145.         }
  5146.         return $this->individualListPagesBase($request, 'discount');
  5147.     }
  5148.     /**
  5149.      * @Route("/posledne-kusy",                                     name="product_all_last_piece_sk", defaults={"_locale":""})
  5150.      * @Route("/{_locale<%supported_locales%>?}/posledne-kusy",     name="product_all_last_piece_sk_locale", defaults={"_locale":""})
  5151.      * @Route("/utolso-darabok",                                    name="product_all_last_piece_hu", defaults={"_locale":""})
  5152.      * @Route("/{_locale<%supported_locales%>?}/utolso-darabok",    name="product_all_last_piece_hu_locale", defaults={"_locale":""})
  5153.      * @param Request $request
  5154.      * @return mixed
  5155.      */
  5156.     public function allLastPieceProductsAction(Request $request)
  5157.     {
  5158.         return $this->individualListPagesBase($request, 'lastPiece');
  5159.     }
  5160.     /**
  5161.      * @param Request $request
  5162.      * @param $listPageType
  5163.      * @return Response
  5164.      * @throws InvalidArgumentException
  5165.      */
  5166.     private function individualListPagesBase(Request $request, $listPageType): Response
  5167.     {
  5168.         $data = [];
  5169.         $seoUrlHelper = $this->getSeoUrlHelper($request);
  5170.         // Search
  5171.         if ($request->get('fs')) {
  5172.             $filterSearch = trim($request->get('fs'));
  5173.         } else {
  5174.             $filterSearch = null;
  5175.         }
  5176.         // Filter Vendor
  5177.         if ($request->get('fv')) {
  5178.             $filterVendor = $request->get('fv');
  5179.         } else {
  5180.             $filterVendor = null;
  5181.         }
  5182.         // Filter Product Type
  5183.         if ($request->get('ft')) {
  5184.             $filterType = $request->get('ft');
  5185.         } else {
  5186.             $filterType = null;
  5187.         }
  5188.         // Filter Badge
  5189.         if ($request->get('fb')) {
  5190.             $filterBadge = $request->get('fb');
  5191.         } else {
  5192.             $filterBadge = null;
  5193.         }
  5194.         // Filter Attribute
  5195.         if ($request->get('fa')) {
  5196.             $filterAttribute = $request->get('fa');
  5197.         } else {
  5198.             $filterAttribute = null;
  5199.         }
  5200.         // Filter Group OR - Create OR groups by attribute ID
  5201.         if ($request->get('fgo')) {
  5202.             $filterGroupOr = $request->get('fgo');
  5203.         } else {
  5204.             $filterGroupOr = null;
  5205.         }
  5206.         // Filter Price
  5207.         if ($request->get('fp')) {
  5208.             $filterPrice = explode('-', $request->get('fp'));
  5209.             if (!empty($filterPrice[0])) {
  5210.                 $filterPriceMin = floor((float)$filterPrice[0]);
  5211.             } else {
  5212.                 $filterPriceMin = null;
  5213.             }
  5214.             if (!empty($filterPrice[1])) {
  5215.                 $filterPriceMax = ceil((float)$filterPrice[1]);
  5216.             } else {
  5217.                 $filterPriceMax = null;
  5218.             }
  5219.         } else {
  5220.             $filterPriceMin = $filterPriceMax = null;
  5221.         }
  5222.         // Filter Discounted
  5223.         if ($listPageType == 'discount') {
  5224.             $filterDiscounted = 1;
  5225.         } else {
  5226.             if ($request->get('fd')) {
  5227.                 $filterDiscounted = (int)$request->get('fd');
  5228.             } else {
  5229.                 $filterDiscounted = null;
  5230.             }
  5231.         }
  5232.         // Filter Last Pieces
  5233.         if ($listPageType == 'lastPiece') {
  5234.             $filterLastPieces = 1;
  5235.         } else {
  5236.             if ($request->get('fl')) {
  5237.                 $filterLastPieces = (int)$request->get('fl');
  5238.             } else {
  5239.                 $filterLastPieces = null;
  5240.             }
  5241.         }
  5242.         // Sort
  5243.         if ($request->get('sort')) {
  5244.             $sort = $request->get('sort');
  5245.         } else {
  5246.             $sort = 'price';
  5247.         }
  5248.         // Order
  5249.         if ($request->get('order')) {
  5250.             $order = $request->get('order');
  5251.         } else {
  5252.             $order = 'asc';
  5253.         }
  5254.         // Page
  5255.         if ($request->get('page')) {
  5256.             $page = $request->get('page');
  5257.         } else {
  5258.             $page = 1;
  5259.         }
  5260.         // Limit
  5261.         if ($request->get('limit')) {
  5262.             $limit = $request->get('limit');
  5263.         } else {
  5264.             $limit = 24;
  5265.         }
  5266.         $multiStore = $this->getMultiStoreHelper($request);
  5267.         $productHelper = $this->getProductHelper($request);
  5268.         $translator = $this->getTranslator();
  5269.         $seoUrl = $this->url($request);
  5270.         $data['customerTypeId'] = $request->getSession()->get('customerTypeId');
  5271.         $data['breadcrumbs'] = [];
  5272.         $data['breadcrumbs'][] = $this->getBreadCrumbsBase($request);
  5273.         // Breadcrumb Arguments
  5274.         $arguments = [];
  5275.         if (!is_null($filterSearch)) {
  5276.             $arguments['fs'] = $filterSearch;
  5277.         }
  5278.         if (!is_null($filterVendor)) {
  5279.             $arguments['fv'] = $filterVendor;
  5280.         }
  5281.         if (!is_null($filterType)) {
  5282.             $arguments['ft'] = $filterType;
  5283.         }
  5284.         if (!is_null($filterBadge)) {
  5285.             $arguments['fb'] = $filterBadge;
  5286.         }
  5287.         if (!is_null($filterAttribute)) {
  5288.             foreach ($filterAttribute as $key => $value) {
  5289.                 $arguments['fa[' . $key . ']'] = $value;
  5290.             }
  5291.         }
  5292.         if (!is_null($filterGroupOr)) {
  5293.             $arguments['fgo'] = $filterGroupOr;
  5294.         }
  5295.         if (!is_null($filterPriceMin) && !is_null($filterPriceMax)) {
  5296.             $arguments['fp'] = $filterPriceMin . '-' . $filterPriceMax;
  5297.         } elseif (!is_null($filterPriceMin) && is_null($filterPriceMax)) {
  5298.             $arguments['fp'] = $filterPriceMin . '-0';
  5299.         } elseif (is_null($filterPriceMin) && !is_null($filterPriceMax)) {
  5300.             $arguments['fp'] = '0-' . $filterPriceMax;
  5301.         }
  5302.         if (!is_null($filterDiscounted)) {
  5303.             $arguments['fd'] = $filterDiscounted;
  5304.         }
  5305.         if (!is_null($filterLastPieces)) {
  5306.             $arguments['fl'] = $filterLastPieces;
  5307.         }
  5308.         if ($request->get('sort')) {
  5309.             $arguments['sort'] = $sort;
  5310.         }
  5311.         if ($request->get('order')) {
  5312.             $arguments['order'] = $order;
  5313.         }
  5314.         if ($request->get('limit')) {
  5315.             $arguments['limit'] = $limit;
  5316.         }
  5317.         $domain = $multiStore->getDomain();
  5318.         $data['pageTitle'] = '';
  5319.         $data['pageDescription'] = '';
  5320.         if ($listPageType == 'discount') {
  5321.             $data['pageTitle'] = $translator->trans('Discount PCs and notebooks');
  5322.             $data['pageDescription'] = $translator->trans('Notebook, PC and monitor sale! Free shipping and Y year warranty on every product.', [
  5323.                 'year' => $this->getWarrantyForNonProductText($domain->getId()),
  5324.             ]);
  5325.         }
  5326.         if ($listPageType == 'lastPiece') {
  5327.             $data['pageTitle'] = $translator->trans('Last pieces');
  5328.             $data['pageDescription'] = $translator->trans('Choose from our last piece products, now with even better price! Y years warranty, free shipping within 24 hours!', [
  5329.                 '%year%' => $this->getWarrantyForNonProductText($domain->getId()),
  5330.             ]);
  5331.         }
  5332.         $argumentsConverted = '';
  5333.         foreach ($arguments as $argKey => $argVal) {
  5334.             $argumentsConverted .= ($argumentsConverted == '' ? '?' : '&') . $argKey . '=' . $argVal;
  5335.         }
  5336.         $data['breadcrumbs'][] = [
  5337.             'text' => $data['pageTitle'],
  5338.             'href' => $request->getUri() . '/' . $argumentsConverted,
  5339.         ];
  5340.         $domain = $multiStore->getDomain();
  5341.         $data['currency'] = $domain->getCurrency();
  5342.         $data['precision'] = $domain->getPricePrecision();
  5343.         $data['products'] = [];
  5344.         $filterData = [
  5345.             'filterSearch' => $filterSearch,
  5346.             'filterVendor' => $filterVendor,
  5347.             'filterType' => $filterType,
  5348.             'filterBadge' => $filterBadge,
  5349.             'filterAttribute' => $filterAttribute,
  5350.             'filterGroupOr' => $filterGroupOr,
  5351.             'filterPriceMin' => $filterPriceMin,
  5352.             'filterPriceMax' => $filterPriceMax,
  5353.             'filterDiscounted' => $filterDiscounted,
  5354.             'filterLastPieces' => $filterLastPieces,
  5355.             'sort' => $sort,
  5356.             'order' => $order,
  5357.             'start' => ($page - 1) * $limit,
  5358.             'limit' => $limit,
  5359.         ];
  5360.         if (!is_null($filterType)) {
  5361.             $data['ncFilter'][] = [
  5362.                 'title' => $this->getEntityManager()->getRepository(ProductType::class)->findOneById($filterType)->getTitle($this->getDatabaseTranslator($request)),
  5363.                 'type' => 'ft',
  5364.             ];
  5365.         }
  5366.         if (!is_null($filterVendor)) {
  5367.             $data['ncFilter'][] = [
  5368.                 'title' => $this->getEntityManager()->getRepository(Vendor::class)->findOneById($filterVendor)->getName($this->getDatabaseTranslator($request)),
  5369.                 'type' => 'fv',
  5370.             ];
  5371.         }
  5372.         $placeholder = $this->getImage('placeholder.png', '')->resize(Image::PRODUCT_LIST_THUMB_WIDTH, Image::PRODUCT_LIST_THUMB_HEIGHT);
  5373.         $results = $productHelper->getStructuredDataByFilters($filterData);
  5374.         foreach ($results as $result) {
  5375.             $image = $placeholder;
  5376.             if (is_object($result['images'])) {
  5377.                 $image = $this->getImage($result['images'], 'product/' . $result['code'])->resize(Image::PRODUCT_LIST_THUMB_WIDTH, Image::PRODUCT_LIST_THUMB_HEIGHT);
  5378.             }
  5379.             $data['products'][] = [
  5380.                 'id' => $result['id'],
  5381.                 'title' => $result['title'],
  5382.                 'vendor' => $result['vendor'],
  5383.                 'labels' => $result['badges'],
  5384.                 'price' => $result['vatPrice'],
  5385.                 'special' => ($result['isDiscounted'] ? $result['discountVatPrice'] : false),
  5386.                 'rawPrice' => $result['rawPrice'],
  5387.                 'rawDiscountPrice' => $result['rawDiscountPrice'],
  5388.                 'image' => $image,
  5389.                 'attributes' => $result['attributes'],
  5390.                 'available' => $result['availableQty'],
  5391.                 'href' => $seoUrl->link('product', [
  5392.                     'product_id' => $result['id'], 
  5393.                     'isBazaar'   => $result['isBazaar'] ?? 0
  5394.                 ]),
  5395.                 'active' => $result['active'],
  5396.                 'typeId' => $result['productTypeId'],
  5397.                 'warrantyYear' => $this->getWarrantyForProductType($domain->getId(), $result['productTypeId'])['year'],
  5398.                 'labelOS' => $this->getProductHelper($request)->getOSLabel($result),
  5399.             ];
  5400.         }
  5401.         // Pagination
  5402.         if (!empty($results)) {
  5403.             $result = $productHelper->getTotalByFilters($filterData);
  5404.             $arguments = [];
  5405.             if (!is_null($filterSearch)) {
  5406.                 $arguments['fs'] = $filterSearch;
  5407.             }
  5408.             if (!is_null($filterVendor)) {
  5409.                 $arguments['fv'] = $filterVendor;
  5410.             }
  5411.             if (!is_null($filterType)) {
  5412.                 $arguments['ft'] = $filterType;
  5413.             }
  5414.             if (!is_null($filterBadge)) {
  5415.                 $arguments['fb'] = $filterBadge;
  5416.             }
  5417.             if (!is_null($filterAttribute)) {
  5418.                 foreach ($filterAttribute as $key => $value) {
  5419.                     $arguments['fa[' . $key . ']'] = $value;
  5420.                 }
  5421.             }
  5422.             if (!is_null($filterGroupOr)) {
  5423.                 $arguments['fgo'] = $filterGroupOr;
  5424.             }
  5425.             if (!is_null($filterPriceMin) && !is_null($filterPriceMax)) {
  5426.                 $arguments['fp'] = $filterPriceMin . '-' . $filterPriceMax;
  5427.             } elseif (!is_null($filterPriceMin) && is_null($filterPriceMax)) {
  5428.                 $arguments['fp'] = $filterPriceMin . '-0';
  5429.             } elseif (is_null($filterPriceMin) && !is_null($filterPriceMax)) {
  5430.                 $arguments['fp'] = '0-' . $filterPriceMax;
  5431.             }
  5432.             if (!is_null($filterDiscounted)) {
  5433.                 $arguments['fd'] = $filterDiscounted;
  5434.             }
  5435.             if (!is_null($filterLastPieces)) {
  5436.                 $arguments['fl'] = $filterLastPieces;
  5437.             }
  5438.             if ($request->get('sort')) {
  5439.                 $arguments['sort'] = $sort;
  5440.             }
  5441.             if ($request->get('order')) {
  5442.                 $arguments['order'] = $order;
  5443.             }
  5444.             if ($request->get('limit')) {
  5445.                 $arguments['limit'] = $limit;
  5446.             }
  5447.             $arguments['page'] = '{page}';
  5448.             $argumentsConverted = '';
  5449.             foreach ($arguments as $argKey => $argVal) {
  5450.                 $argumentsConverted .= ($argumentsConverted == '' ? '?' : '&') . $argKey . '=' . $argVal;
  5451.             }
  5452.             $data['pagination'] = [
  5453.                 'total' => $result,
  5454.                 'page' => $page,
  5455.                 'limit' => $limit,
  5456.                 'url' => strtok($request->getUri(), '?') . $argumentsConverted,
  5457.             ];
  5458.         } else {
  5459.             $data['pagination'] = [];
  5460.         }
  5461.         // Filter Options
  5462.         $filters = $productHelper->buildFilterOptions($filterData, [
  5463.             'search' => true,
  5464.         ]);
  5465.         $data['filters'] = $filters;
  5466.         if (!is_null($filterSearch)) {
  5467.             $data['filterSearch'] = $filterSearch;
  5468.         } else {
  5469.             $data['filterSearch'] = '';
  5470.         }
  5471.         if (!is_null($filterVendor)) {
  5472.             $data['filterVendor'] = explode(',', $filterVendor);
  5473.         } else {
  5474.             $data['filterVendor'] = [];
  5475.         }
  5476.         if (!is_null($filterType)) {
  5477.             $data['filterType'] = explode(',', $filterType);
  5478.         } else {
  5479.             $data['filterType'] = [];
  5480.         }
  5481.         if (!is_null($filterBadge)) {
  5482.             $data['filterBadge'] = explode(',', $filterBadge);
  5483.         } else {
  5484.             $data['filterBadge'] = [];
  5485.         }
  5486.         if (!is_null($filterAttribute)) {
  5487.             $data['filterAttribute'] = $data['filterAttributes'] = [];
  5488.             foreach ($filterAttribute as $attributeId => $attribute) {
  5489.                 $options = explode(',', $attribute);
  5490.                 foreach ($options as $option) {
  5491.                     array_push($data['filterAttribute'], $option);
  5492.                 }
  5493.                 if ($attributeId !== 101) {
  5494.                     $data['filterAttributes'][$attributeId] = $attribute;
  5495.                 }
  5496.             }
  5497.         } else {
  5498.             $data['filterAttribute'] = $data['filterAttributes'] = [];
  5499.         }
  5500.         if (!is_null($filterGroupOr)) {
  5501.             $data['filterGroupOr'] = explode(',', $filterGroupOr);
  5502.         } else {
  5503.             $data['filterGroupOr'] = [];
  5504.         }
  5505.         if (!is_null($filterPriceMin)) {
  5506.             $data['filterPriceMin'] = $filterPriceMin;
  5507.         } else {
  5508.             $data['filterPriceMin'] = false;
  5509.         }
  5510.         if (!is_null($filterPriceMax)) {
  5511.             $data['filterPriceMax'] = $filterPriceMax;
  5512.         } else {
  5513.             $data['filterPriceMax'] = false;
  5514.         }
  5515.         if (!is_null($filterDiscounted)) {
  5516.             $data['filterDiscounted'] = $filterDiscounted;
  5517.         } else {
  5518.             $data['filterDiscounted'] = false;
  5519.         }
  5520.         if (!is_null($filterLastPieces)) {
  5521.             $data['filterLastPieces'] = $filterLastPieces;
  5522.         } else {
  5523.             $data['filterLastPieces'] = false;
  5524.         }
  5525.         // Filter Action
  5526.         $arguments = [];
  5527.         $data['actionFiltered'] = false;
  5528.         if ($request->get('sort')) {
  5529.             $arguments['sort'] = $sort;
  5530.             $data['actionFiltered'] = true;
  5531.         }
  5532.         if ($request->get('order')) {
  5533.             $arguments['order'] = $order;
  5534.             $data['actionFiltered'] = true;
  5535.         }
  5536.         if ($request->get('limit')) {
  5537.             $arguments['limit'] = $limit;
  5538.             $data['actionFiltered'] = true;
  5539.         }
  5540.         $argumentsConverted = '';
  5541.         foreach ($arguments as $argKey => $argVal) {
  5542.             $argumentsConverted .= ($argumentsConverted == '' ? '?' : '&') . $argKey . '=' . $argVal;
  5543.         }
  5544.         $data['action'] = strtok($request->getUri(), '?') . $argumentsConverted;
  5545.         // Sort Arguments
  5546.         $arguments = [];
  5547.         if (!is_null($filterSearch)) {
  5548.             $arguments['fs'] = $filterSearch;
  5549.         }
  5550.         if (!is_null($filterVendor)) {
  5551.             $arguments['fv'] = $filterVendor;
  5552.         }
  5553.         if (!is_null($filterType)) {
  5554.             $arguments['ft'] = $filterType;
  5555.         }
  5556.         if (!is_null($filterBadge)) {
  5557.             $arguments['fb'] = $filterBadge;
  5558.         }
  5559.         if (!is_null($filterAttribute)) {
  5560.             foreach ($filterAttribute as $key => $value) {
  5561.                 $arguments['fa[' . $key . ']'] = $value;
  5562.             }
  5563.         }
  5564.         if (!is_null($filterGroupOr)) {
  5565.             $arguments['fgo'] = $filterGroupOr;
  5566.         }
  5567.         if (!is_null($filterPriceMin) && !is_null($filterPriceMax)) {
  5568.             $arguments['fp'] = $filterPriceMin . '-' . $filterPriceMax;
  5569.         } elseif (!is_null($filterPriceMin) && is_null($filterPriceMax)) {
  5570.             $arguments['fp'] = $filterPriceMin . '-0';
  5571.         } elseif (is_null($filterPriceMin) && !is_null($filterPriceMax)) {
  5572.             $arguments['fp'] = '0-' . $filterPriceMax;
  5573.         }
  5574.         if (!is_null($filterDiscounted)) {
  5575.             $arguments['fd'] = $filterDiscounted;
  5576.         }
  5577.         if (!is_null($filterLastPieces)) {
  5578.             $arguments['fl'] = $filterLastPieces;
  5579.         }
  5580.         if ($request->get('sort')) {
  5581.             $arguments['sort'] = $sort;
  5582.         }
  5583.         if ($request->get('order')) {
  5584.             $arguments['order'] = $order;
  5585.         }
  5586.         if ($request->get('limit')) {
  5587.             $arguments['limit'] = $limit;
  5588.         }
  5589.         $argumentsConverted = '';
  5590.         foreach ($arguments as $argKey => $argVal) {
  5591.             $argumentsConverted .= ($argumentsConverted == '' ? '?' : '&') . $argKey . '=' . $argVal;
  5592.         }
  5593.         // Sort By
  5594.         $data['sortOrders'] = [];
  5595.         $data['sortOrders'][] = [
  5596.             'text' => $translator->trans('Sort by') . ': ' . $translator->trans('Default'),
  5597.             'value' => 'default-asc',
  5598.             'href' => $data['action'] . ($argumentsConverted == '' ? '?' : $argumentsConverted . '&') . 'sort=default&order=asc',
  5599.         ];
  5600.         $data['sortOrders'][] = [
  5601.             'text' => $translator->trans('Sort by') . ': ' . $translator->trans('Name') . ' (' . $translator->trans('A to Z') . ')',
  5602.             'value' => 'name-asc',
  5603.             'href' => $data['action'] . ($argumentsConverted == '' ? '?' : $argumentsConverted . '&') . 'sort=name&order=asc',
  5604.         ];
  5605.         $data['sortOrders'][] = [
  5606.             'text' => $translator->trans('Sort by') . ': ' . $translator->trans('Name') . ' (' . $translator->trans('Z to A') . ')',
  5607.             'value' => 'name-desc',
  5608.             'href' => $data['action'] . ($argumentsConverted == '' ? '?' : $argumentsConverted . '&') . 'sort=name&order=desc',
  5609.         ];
  5610.         $data['sortOrders'][] = [
  5611.             'text' => $translator->trans('Sort by') . ': ' . $translator->trans('Price') . ' (' . $translator->trans('low to high') . ')',
  5612.             'value' => 'price-asc',
  5613.             'href' => $data['action'] . ($argumentsConverted == '' ? '?' : $argumentsConverted . '&') . 'sort=price&order=asc',
  5614.         ];
  5615.         $data['sortOrders'][] = [
  5616.             'text' => $translator->trans('Sort by') . ': ' . $translator->trans('Price') . ' (' . $translator->trans('high to low') . ')',
  5617.             'value' => 'price-desc',
  5618.             'href' => $data['action'] . ($argumentsConverted == '' ? '?' : $argumentsConverted . '&') . 'sort=price&order=desc',
  5619.         ];
  5620.         $data['sort'] = $sort;
  5621.         $data['order'] = $order;
  5622.         // Limit
  5623.         $data['limits'] = [];
  5624.         $limits = [12, 24, 48, 96];
  5625.         foreach ($limits as $value) {
  5626.             $data['limits'][] = [
  5627.                 'text' => $value,
  5628.                 'value' => $value,
  5629.                 'href' => $data['action'] . ($argumentsConverted == '' ? '?' : $argumentsConverted . '&') . 'limit=' . $value,
  5630.             ];
  5631.         }
  5632.         $data['limit'] = $limit;
  5633.         $data['salesManager'] = [];
  5634.         if ($data['customerTypeId'] == MultiStore::CUSTOMER_TYPE_WHOLESALE) {
  5635.             $loggedInCustomer = $this->getLoginHelper($request)->getLoggedInCustomer();
  5636.             $salesManager = $loggedInCustomer->getSalesManager();
  5637.             $data['salesManager']['name'] = $salesManager->getFirstName();
  5638.             $data['salesManager']['username'] = $salesManager->getUsername();
  5639.             $data['salesManager']['phone'] = $salesManager->getPhone();
  5640.         }
  5641.         $data['webshop_phone_number'] = $this->getContactInfos()['phone.webshop.' . $domain->getLanguage()->getCode() . '.' . $domain->getType()];
  5642.         $data['header'] = $this->getHeader($request);
  5643.         $data['footer'] = $this->getFooter($request);
  5644.         $data['contentBottom'] = $this->getContentBottom($request);
  5645.         $domainId = $domain->getId();
  5646.         $data['warrantyYear'] = $this->getWarrantyForNonProductText($domainId);
  5647.         $data['listPageType'] = $listPageType;
  5648.         switch ($domainId) {
  5649.             case 1:
  5650.             case 2:
  5651.                 $data['quality_info_link'] = $seoUrlHelper->link('page', [
  5652.                     'static_id' => 11,
  5653.                 ]);
  5654.                 $data['notebooks_discount_link'] = $seoUrl->link('category', [
  5655.                     'path' => 5,
  5656.                     'fd' => 1,
  5657.                 ]);
  5658.                 $data['pcs_discount_link'] = $seoUrl->link('category', [
  5659.                     'path' => 4,
  5660.                     'fd' => 1,
  5661.                 ]);
  5662.                 $data['monitors_discount_link'] = $seoUrl->link('category', [
  5663.                     'path' => 6,
  5664.                     'fd' => 1,
  5665.                 ]);
  5666.                 break;
  5667.             case 3:
  5668.             case 4:
  5669.                 $data['quality_info_link'] = $seoUrlHelper->link('page', [
  5670.                     'static_id' => 27,
  5671.                 ]);
  5672.                 $data['notebooks_discount_link'] = $seoUrl->link('category', [
  5673.                     'path' => 56,
  5674.                     'fd' => 1,
  5675.                 ]);
  5676.                 $data['pcs_discount_link'] = $seoUrl->link('category', [
  5677.                     'path' => 48,
  5678.                     'fd' => 1,
  5679.                 ]);
  5680.                 $data['monitors_discount_link'] = $seoUrl->link('category', [
  5681.                     'path' => 78,
  5682.                     'fd' => 1,
  5683.                 ]);
  5684.                 break;
  5685.             case 9:
  5686.             case 5:
  5687.                 $data['quality_info_link'] = $seoUrlHelper->link('page', [
  5688.                     'static_id' => 60,
  5689.                 ]);
  5690.                 $data['notebooks_discount_link'] = $seoUrl->link('category', [
  5691.                     'path' => 130,
  5692.                     'fd' => 1,
  5693.                 ]);
  5694.                 $data['pcs_discount_link'] = $seoUrl->link('category', [
  5695.                     'path' => 122,
  5696.                     'fd' => 1,
  5697.                 ]);
  5698.                 $data['monitors_discount_link'] = $seoUrl->link('category', [
  5699.                     'path' => 149,
  5700.                     'fd' => 1,
  5701.                 ]);
  5702.                 break;
  5703.             default:
  5704.                 $data['quality_info_link'] = '';
  5705.                 $data['notebooks_discount_link'] = $seoUrl->link('category', [
  5706.                     'path' => 5,
  5707.                     'fd' => 1,
  5708.                 ]);
  5709.                 $data['pcs_discount_link'] = $seoUrl->link('category', [
  5710.                     'path' => 4,
  5711.                     'fd' => 1,
  5712.                 ]);
  5713.                 $data['monitors_discount_link'] = $seoUrl->link('category', [
  5714.                     'path' => 6,
  5715.                     'fd' => 1,
  5716.                 ]);
  5717.         }
  5718.         return $this->render('AtechNetCoreBundle/Product/individualListPage.html.twig', $data);
  5719.     }
  5720.     /**
  5721.      * @Route("/product/{productId}/review", name="product_review", defaults={"_locale":""})
  5722.      * @Route("/{_locale<%supported_locales%>?}/product/{productId}/review", name="product_review_locale", defaults={"_locale":""})
  5723.      * @param int $productId
  5724.      * @param Request $request
  5725.      * @return Response
  5726.      */
  5727.     public function reviewAction(int $productId, Request $request): Response
  5728.     {
  5729.         $data = [];
  5730.         $multiStore = $this->getMultiStoreHelper($request);
  5731.         if ($request->get('page')) {
  5732.             $page = $request->get('page');
  5733.         } else {
  5734.             $page = 1;
  5735.         }
  5736.         $limit = 6;
  5737.         $data['reviews'] = [];
  5738.         $entityManager = $this->getEntityManager();
  5739.         $results = $entityManager->getRepository(Review::class)->findBy(
  5740.             [
  5741.                 'language' => $multiStore->getDefaultLanguageId(),
  5742.                 'type' => Review::TYPE_PRODUCT,
  5743.                 'product' => $productId,
  5744.                 'approved' => 1,
  5745.             ],
  5746.             [
  5747.                 'created' => 'DESC',
  5748.             ],
  5749.             $limit,
  5750.             (($page - 1) * $limit)
  5751.         );
  5752.         $total = $entityManager->getRepository(Review::class)->findBy([
  5753.             'language' => $multiStore->getDefaultLanguageId(),
  5754.             'type' => Review::TYPE_PRODUCT,
  5755.             'product' => $productId,
  5756.             'approved' => 1,
  5757.         ]);
  5758.         foreach ($results as $result) {
  5759.             $data['reviews'][] = [
  5760.                 'name' => $result->getName(),
  5761.                 'text' => $result->getText(),
  5762.                 'rating' => $result->getStars(),
  5763.             ];
  5764.         }
  5765.         $data['pagination'] = [
  5766.             'total' => count($total),
  5767.             'page' => $page,
  5768.             'limit' => $limit,
  5769.             'url' => $this->generateUrl('review_list_' . $multiStore->getLanguage()->getCode(), [
  5770.                 'productId' => $productId,
  5771.                 'page' => '{page}',
  5772.             ]),
  5773.         ];
  5774.         return $this->render('AtechNetCoreBundle/Module/review.html.twig', $data);
  5775.     }
  5776.     /**
  5777.      * @param Request $request
  5778.      * @return false|string
  5779.      */
  5780.     private function onlyLastParamHandler(Request $request)
  5781.     {
  5782.         if ($request->get('only-last')) {
  5783.             $explodedString = explode('-', $request->get('only-last'));
  5784.             $number = $explodedString[0];
  5785.             $unit = $explodedString[1];
  5786.             switch ($unit) {
  5787.                 case 'hour':
  5788.                     $unit = 'H';
  5789.                     break;
  5790.                 case 'minute':
  5791.                     $unit = 'M';
  5792.                     break;
  5793.             }
  5794.             return (
  5795.                 $number > 0 && (
  5796.                     $unit == 'H' && $number <= 12 ||
  5797.                     $unit == 'M' && $number <= 720
  5798.                 )
  5799.             ) ? (new \DateTime())->sub(new \DateInterval('PT' . $number . $unit)) : 'invalid';
  5800.         } else {
  5801.             return false;
  5802.         }
  5803.     }
  5804.     /**
  5805.      * @Route("/feed/{token}", name="product_feed", defaults={"_locale":""})
  5806.      * @param Request $request
  5807.      * @param $token
  5808.      * @return Response
  5809.      * @throws \Psr\SimpleCache\InvalidArgumentException
  5810.      */
  5811.     public function feedAction(Request $request, $token): Response
  5812.     {
  5813.         if (isset($token) && $token != '' && strlen($token) > 10) {
  5814.             $entityManager = $this->getEntityManager();
  5815.             $productFeed = $entityManager->createQuery("SELECT cpf
  5816.                   FROM AtechNetCoreBundle:CustomerProductFeed cpf
  5817.                   WHERE cpf.token = :token AND cpf.expire > :expire AND cpf.active = 1")
  5818.                 ->setParameters([
  5819.                     'token' => $token,
  5820.                     'expire' => (new \DateTime()),
  5821.                 ])
  5822.                 ->setMaxResults(1)
  5823.                 ->getResult();
  5824.             if (isset($productFeed[0])) {
  5825.                 $productFeed = $productFeed[0];
  5826.                 $cache = $this->cache;
  5827.                 $customer = $productFeed->getCustomer();
  5828.                 $seoUrlHelper = $this->getSeoUrlHelper($request);
  5829.                 $environment = $this->getEnvironment();
  5830.                 $isNlc = $customer->getId() == 18733;
  5831.                 $isCopyandMore = $customer->getId() == 31170;
  5832.                 $isAndreaShop = $customer->getId() == Customer::ANDREASHOP_ID;
  5833.                 $isMerxu = $customer->getId() == 56655;
  5834.                 $isAdLogic = $customer->getId() == 87351;
  5835.                 if ($isMerxu) {
  5836.                     $domain = $entityManager->getRepository(Domain::class)->findOneById(Domain::DOMAIN_ID_WS_SK);
  5837.                 } else {
  5838.                     $domain = $customer->getDomain();
  5839.                 }
  5840.                 $cacheKey = 'partner.feed.v3.domain.' . $domain->getId() . '.' . ($isNlc ? 1 : 0) . '.' . ($isCopyandMore ? 1 : 0) . '.' . ($isAndreaShop ? 1 : 0) . '.' . ($isMerxu ? 1 : 0) . '.' . ($isAdLogic ? 1 : 0);
  5841.                 $cacheItem = $cache->getItem($cacheKey);
  5842.                 $onlyLast = $this->onlyLastParamHandler($request);
  5843.                 if ($onlyLast == 'invalid') {
  5844.                     return new Response('Invalid only-last parameter!');
  5845.                 }
  5846.                 if ($cacheItem->isHit() && !$onlyLast) {
  5847.                     $xml = $cacheItem->get();
  5848.                 } else {
  5849.                     $qualityStatuses = Product::getQualityStatusChoices();
  5850.                     $translator = new DatabaseTranslator($entityManager, $domain->getId());
  5851.                     $queryParams = [
  5852.                         'domain' => $domain,
  5853.                         'bazarQualityStatus' => Product::QualityStatus_Bazaar,
  5854.                     ];
  5855.                     $setCache = false;
  5856.                     $allowedProductTypesIDs = [
  5857.                         1, 4, 5, 6, 7, 35, 41, 44, 45, 46, 52, 60, 64, 66, 68, 69, 75, 76, 77, 84, 90, 103, 104, 106, 107, 110, 113, 114, 116, 138, 145, 147, 149, 150, 154, 155, 156, 160, 167, 180, 182, 184, 185, 192, 199,
  5858.                     ];
  5859.                     if ($onlyLast) {
  5860.                         $queryParams['onlyLast'] = $onlyLast;
  5861.                         $products = $entityManager->createQuery("SELECT p
  5862.                           FROM AtechNetCoreBundle:Product p
  5863.                           LEFT JOIN p.metas pm
  5864.                           LEFT JOIN p.orderItems poi
  5865.                           WHERE pm.domain = :domain
  5866.                             AND p.updated > :onlyLast
  5867.                             AND poi IS NOT null
  5868.                             AND p.qualityStatus != :bazarQualityStatus")
  5869.                             ->setParameters($queryParams)
  5870.                             ->getResult();
  5871.                     } elseif ($isAdLogic) {
  5872.                         $products = $entityManager->createQuery("SELECT p
  5873.                           FROM AtechNetCoreBundle:Product p
  5874.                           LEFT JOIN p.metas pm
  5875.                           WHERE p.available > 0
  5876.                             AND pm.domain = :domain
  5877.                             AND pm.listed = 1
  5878.                             AND pm.active = 1
  5879.                             AND pm.orderable = 1
  5880.                             AND (p.qualityStatus = :bazarQualityStatus OR p.type IN (" . implode(',', $this->getAccessoriesProductTypeIdList()) . "))")
  5881.                             ->setParameters($queryParams)
  5882.                             ->getResult();
  5883.                         $setCache = true;
  5884.                     } else {
  5885.                         $products = $entityManager->createQuery("SELECT p
  5886.                           FROM AtechNetCoreBundle:Product p
  5887.                           LEFT JOIN p.metas pm
  5888.                           WHERE p.available > 0
  5889.                             AND pm.domain = :domain
  5890.                             AND pm.listed = 1
  5891.                             AND pm.active = 1
  5892.                             AND pm.orderable = 1
  5893.                             AND p.qualityStatus != :bazarQualityStatus" . ($customer->getId() == 56655 ? " AND p.type IN (41,44,52,60,116)" : " AND p.type IN (" . implode(',', $allowedProductTypesIDs) . ")"))
  5894.                             ->setParameters($queryParams)
  5895.                             ->getResult();
  5896.                         $setCache = true;
  5897.                     }
  5898.                     $xml = '<?xml version="1.0" encoding="utf-8" ?><SHOP>';
  5899.                     $multistorHelper = $this->getMultiStoreHelper($request);
  5900.                     $requestDomain = $multistorHelper->getDomain();
  5901.                     $language = $requestDomain->getLanguage();
  5902.                     $categoryPageTitles = [];
  5903.                     foreach ($products as $product) {
  5904.                         $productMeta = $product->getDomainMeta($domain);
  5905.                         if (!$productMeta) {
  5906.                             continue;
  5907.                         }
  5908.                         $price = $productMeta->isDiscounted() ? $productMeta->getDomainVatDiscount() : $productMeta->getDomainVatPrice();
  5909.                         $originalPrice = $productMeta->isDiscounted() ? $productMeta->getDomainVatPrice() : '';
  5910.                         if (1 > $price) {
  5911.                             continue;
  5912.                         }
  5913.                         $image = '';
  5914.                         $images = '';
  5915.                         if ($environment == 'prod') {
  5916.                             $photos = $product->getAlbum()->getPhotos();
  5917.                             if (count($photos) > 0) {
  5918.                                 $photos = Collections::sort($photos);
  5919.                                 foreach ($photos as $photo) {
  5920.                                     if (is_object($photo)) {
  5921.                                         if ($image == '') {
  5922.                                             $image = $this->getImage($photo, 'product/' . $product->getCode(), true)->resize(Image::PRODUCT_VIEW_THUMB_WIDTH, Image::PRODUCT_VIEW_THUMB_HEIGHT);
  5923.                                         } else {
  5924.                                             $images .= '<IMAGE_URL>' . $this->getImage($photo, 'product/' . $product->getCode(), true)->resize(Image::PRODUCT_VIEW_THUMB_WIDTH, Image::PRODUCT_VIEW_THUMB_HEIGHT) . '</IMAGE_URL>';
  5925.                                         }
  5926.                                     }
  5927.                                 }
  5928.                             }
  5929.                         }
  5930.                         if ($productMeta->getDomainVatSuggestedPrice() != 0) {
  5931.                             $suggestedVatPrice = $productMeta->getDomainVatSuggestedPrice();
  5932.                         } else {
  5933.                             $suggestedPrice = $this->calculateSuggestedPrice($productMeta);
  5934.                             $suggestedVatPrice = $domain->createVatPrice($suggestedPrice);
  5935.                         }
  5936.                         $subCategories = '<SUB_CATEGORIES>';
  5937.                         foreach ($product->getBadges() as $badge) {
  5938.                             if ($badge != 'win10') {
  5939.                                 $subCategories .= '<SUB_CAT>' . ucfirst($badge) . '</SUB_CAT>';
  5940.                             }
  5941.                         }
  5942.                         $subCategories .= '</SUB_CATEGORIES>';
  5943.                         $created = $product->getCreated()->format('Y-m-d, H:i');
  5944.                         $updated = !is_null($product->getUpdated()) ? $product->getUpdated()->format('Y-m-d, H:i') : '-';
  5945.                         $productType = $product->getType();
  5946.                         $categoryValue = ($isCopyandMore ? trim($productType->getTitle($translator)) : trim($productType->getTitle()));
  5947.                         $categoryPageWithParent = $productType->getCategoryPageWithParentByDomain($requestDomain);
  5948.                         $parentCategoryTitle = "<FULL_CATEGORY>";
  5949.                         if ($categoryPageWithParent) {
  5950.                             $parentCategoryId = $categoryPageWithParent->getParentCategory()->getId();
  5951.                             if (!isset($categoryPageTitles[$parentCategoryId])) {
  5952.                                 $pageInfo = $entityManager->getRepository(PageMeta::class)->findOneBy([
  5953.                                     'categoryPage' => $parentCategoryId,
  5954.                                     'language' => $language->getId(),
  5955.                                 ]);
  5956.                                 if ($isAdLogic) {
  5957.                                     $categoryPageTitles[$parentCategoryId] = $translator->trans(trim($pageInfo->getTitle()));
  5958.                                 } else {
  5959.                                     $categoryPageTitles[$parentCategoryId] = trim($pageInfo->getTitle());
  5960.                                 }
  5961.                                 if ($pageInfo) {
  5962.                                     if ($isAdLogic) {
  5963.                                         $categoryPageTitles[$parentCategoryId] = $translator->trans(trim($pageInfo->getTitle()));
  5964.                                     } else {
  5965.                                         $categoryPageTitles[$parentCategoryId] = trim($pageInfo->getTitle());
  5966.                                     }
  5967.                                 }
  5968.                             }
  5969.                             if ($isAdLogic) {
  5970.                                 $categoryValue = $translator->trans($categoryValue);
  5971.                             }
  5972.                             if (isset($categoryPageTitles[$parentCategoryId])) {
  5973.                                 $parentCategoryTitle .= $categoryPageTitles[$parentCategoryId] . " | " . $categoryValue;
  5974.                             } else {
  5975.                                 $parentCategoryTitle .= $categoryValue;
  5976.                             }
  5977.                         }
  5978.                         $parentCategoryTitle .= "</FULL_CATEGORY>";
  5979.                         if ($isAdLogic && $parentCategoryTitle == "<FULL_CATEGORY></FULL_CATEGORY>") {
  5980.                             if ($isAdLogic) {
  5981.                                 $categoryValue = $translator->trans($categoryValue);
  5982.                             }
  5983.                             $parentCategoryTitle = "<FULL_CATEGORY>" . $categoryValue . "</FULL_CATEGORY>";
  5984.                         }
  5985.                         $ean = '';
  5986.                         if ($isAndreaShop) {
  5987.                             if (is_null($product->getEan()) || $product->getEan() == '') {
  5988.                                 $ean = $product->getFormattedEan();
  5989.                             } else {
  5990.                                 $ean = $product->getEan();
  5991.                             }
  5992.                         } else {
  5993.                             if (!is_null($product->getEan()) && $product->getEan() != '') {
  5994.                                 $ean = $product->getEan();
  5995.                             }
  5996.                         }
  5997.                         $xml .= "<SHOPITEM>
  5998.                             <ITEM_ID>" . $product->getId() . "</ITEM_ID>
  5999.                             <CODE>" . $product->getCode() . "</CODE>
  6000.                             <EAN>" . $ean . "</EAN>
  6001.                             <NAME><![CDATA[" . ($isCopyandMore ? $product->getName() : $product->getFullTitle($translator)) . "]]></NAME>
  6002.                             <VENDOR><![CDATA[" . $product->getVendor()->getName() . "]]></VENDOR>
  6003.                             <SHORT_DESCRIPTION><![CDATA[" . $product->getDescription() . "]]></SHORT_DESCRIPTION>
  6004.                             <DESCRIPTION><![CDATA[" . preg_replace('#<[^>]+>#', ' ', $productMeta->getFullDescription($translator)) . "]]></DESCRIPTION>
  6005.                             <IMAGE_URL>" . $image . "</IMAGE_URL>
  6006.                             <PRODUCT_URL>" . $seoUrlHelper->link('product', [
  6007.                             'product_id' => $product->getId(),
  6008.                         ]) . "</PRODUCT_URL>
  6009.                             <PRICE>" . $price . "</PRICE>
  6010.                             <ORIGINAL_PRICE>" . $originalPrice . "</ORIGINAL_PRICE>
  6011.                             <SUGGESTED_PRICE>" . $suggestedVatPrice . "</SUGGESTED_PRICE>
  6012.                             <CATEGORY>$categoryValue</CATEGORY>
  6013.                             " . $parentCategoryTitle . "
  6014.                             " . $subCategories . "
  6015.                             <QUALITY>" . $this->getTranslator()->trans(strtolower($qualityStatuses[$product->getQualityStatus()])) . "</QUALITY>
  6016.                             <IN_STOCK>" . $product->getAvailable() . "</IN_STOCK>
  6017.                             <CREATED>" . $created . "</CREATED>
  6018.                             <UPDATED>" . $updated . "</UPDATED>
  6019.                             <IMAGES>" . $images . "</IMAGES>";
  6020.                         if ($isAdLogic) {
  6021.                             if ($product->getWeight() > 0) {
  6022.                                 $xml .= "<Suly>" . number_format($product->getWeight() / 1000, 2, '.', '') . "</Suly>";
  6023.                             }
  6024.                             foreach ($product->getSpecificationProductAttributeOptions() as $pao) {
  6025.                                 $ao = $pao->getOption();
  6026.                                 if ($ao->getAttribute()->getId() == 95) {
  6027.                                     continue;
  6028.                                 }
  6029.                                 if (!isset($attrTitles[$ao->getAttribute()->getId()])) {
  6030.                                     $attrTitles[$ao->getAttribute()->getId()] = $ao->getAttribute()->getTitle($translator);
  6031.                                 }
  6032.                                 $attrTitle = $attrTitles[$ao->getAttribute()->getId()];
  6033.                                 if (!isset($attrOptTitles[$ao->getId()])) {
  6034.                                     $attrOptTitles[$ao->getId()] = $ao->getTitle($translator);
  6035.                                 }
  6036.                                 $attrOptTitle = $attrOptTitles[$ao->getId()];
  6037.                                 $attributeTitle = $this->removeSpecialCharacters($attrTitle);
  6038.                                 if ($attributeTitle != '') {
  6039.                                     $xml .= "<" . $attributeTitle . ">" . str_replace('&', '&amp;', $attrOptTitle) . "</" . $attributeTitle . ">";
  6040.                                 }
  6041.                             }
  6042.                         } else {
  6043.                             $xml .= "<CONFIGURATION>";
  6044.                             /**
  6045.                              * @var Product $product
  6046.                              * @var ProductAttribute $pao
  6047.                              *
  6048.                              */
  6049.                             foreach ($product->getSpecificationProductAttributeOptions() as $pao) {
  6050.                                 $ao = $pao->getOption();
  6051.                                 if ($ao->getAttribute()->getId() == 95) {
  6052.                                     continue;
  6053.                                 }
  6054.                                 if (!isset($attrTitles[$ao->getAttribute()->getId()])) {
  6055.                                     $attrTitles[$ao->getAttribute()->getId()] = $ao->getAttribute()->getTitle($translator);
  6056.                                 }
  6057.                                 $attrTitle = $attrTitles[$ao->getAttribute()->getId()];
  6058.                                 if (!isset($attrOptTitles[$ao->getId()])) {
  6059.                                     $attrOptTitles[$ao->getId()] = $ao->getTitle($translator);
  6060.                                 }
  6061.                                 $attrOptTitle = $attrOptTitles[$ao->getId()];
  6062.                                 if ($isAdLogic) {
  6063.                                     $attributeTitle = $this->removeSpecialCharacters($attrTitle);
  6064.                                     if ($attributeTitle != '') {
  6065.                                         $xml .= "<ATTR>
  6066.                                         <" . $attributeTitle . ">" . str_replace('&', '&amp;', $attrOptTitle) . "</" . $attributeTitle . ">
  6067.                                     </ATTR>";
  6068.                                     }
  6069.                                 } else {
  6070.                                     $xml .= "<ATTR>
  6071.                                     " . ($pao->getMultiplier() > 0 ? '<QTY>' . $pao->getMultiplier() . '</QTY>' : '') . "
  6072.                                     <TITLE>" . ($isNlc ? '<![CDATA[' : '') . $attrTitle . ($isNlc ? ']]>' : '') . "</TITLE>
  6073.                                     <VALUE>" . ($isNlc ? '<![CDATA[' : '') . str_replace('&', '&amp;', $attrOptTitle) . ($isNlc ? ']]>' : '') . "</VALUE>
  6074.                                 </ATTR>";
  6075.                                 }
  6076.                             }
  6077.                             $xml .= "</CONFIGURATION>";
  6078.                         }
  6079.                         $xml .= "</SHOPITEM>\n";
  6080.                     }
  6081.                     $xml .= '</SHOP>';
  6082.                     if ($setCache) {
  6083.                         $cacheItem->set($xml);
  6084.                         $cacheItem->expiresAfter(self::CACHE_LIFETIME_4_HOUR);
  6085.                         $cache->save($cacheItem);
  6086.                     }
  6087.                 }
  6088.                 $productFeed->setValidRequests($productFeed->getValidRequests() + 1);
  6089.                 $entityManager->flush();
  6090.                 $response = new Response($xml);
  6091.                 $response->headers->set('Content-Type', 'xml');
  6092.                 return $response;
  6093.             }
  6094.         }
  6095.         return new Response('Something went wrong, please contact your sales manager!');
  6096.     }
  6097.     /**
  6098.      * @Route("/techbazar-feed/{token}", name="tech_baazar_feed", defaults={"_locale":""})
  6099.      * @param Request $request
  6100.      * @param $token
  6101.      * @return Response
  6102.      * @throws \Psr\SimpleCache\InvalidArgumentException
  6103.      */
  6104.     public function techBazarFeedAction(Request $request, $token): Response
  6105.     {
  6106.         if ($token == '0854032424-jg439043240523-ji349t430k9d0932-4j8g34ds0tu4sdl') {
  6107.             $entityManager = $this->getEntityManager();
  6108.             $cache = $this->cache;
  6109.             $seoUrlHelper = $this->getSeoUrlHelper($request);
  6110.             $environment = $this->getEnvironment();
  6111.             $productRepository = $entityManager->getRepository(Product::class);
  6112.             $domain = $this->getMultiStoreHelper($request)->getDomain();
  6113.             $cacheKey = 'techBazar.feed.v5.' . $domain->getId();
  6114.             $cacheItem = $cache->getItem($cacheKey);
  6115.             if ($cacheItem->isHit()) {
  6116.                 $xml = $cacheItem->get();
  6117.             } else {
  6118.                 $qualityStatuses = Product::getQualityStatusChoices();
  6119.                 $translator = new DatabaseTranslator($entityManager, $domain->getId());
  6120.                 $queryParams = [
  6121.                     'domain' => $domain,
  6122.                     'bazarQualityStatus' => Product::QualityStatus_Bazaar,
  6123.                 ];
  6124.                 $products = $entityManager->createQuery("SELECT p
  6125.                   FROM AtechNetCoreBundle:Product p
  6126.                   LEFT JOIN p.metas pm
  6127.                   WHERE p.available > 0
  6128.                     AND pm.domain = :domain
  6129.                     AND pm.listed = 1
  6130.                     AND pm.active = 1
  6131.                     AND pm.orderable = 1
  6132.                     AND (p.qualityStatus = :bazarQualityStatus OR p.type IN (" . implode(',', $this->getAccessoriesProductTypeIdList()) . "))")
  6133.                     ->setParameters($queryParams)
  6134.                     ->getResult();
  6135.                 $xml = '<?xml version="1.0" encoding="utf-8" ?><SHOP>';
  6136.                 $multistorHelper = $this->getMultiStoreHelper($request);
  6137.                 $requestDomain = $multistorHelper->getDomain();
  6138.                 $language = $requestDomain->getLanguage();
  6139.                 $categoryPageTitles = [];
  6140.                 $errorCodeCache = [];
  6141.                 /**
  6142.                  * @var Product $product
  6143.                  */
  6144.                 foreach ($products as $product) {
  6145.                     $productMeta = $product->getDomainMeta($domain);
  6146.                     if (!$productMeta) {
  6147.                         continue;
  6148.                     }
  6149.                     $price = $productMeta->isDiscounted() ? $productMeta->getDomainVatDiscount() : $productMeta->getDomainVatPrice();
  6150.                     $originalPrice = $productMeta->isDiscounted() ? $productMeta->getDomainVatPrice() : '';
  6151.                     if ($price < 1) {
  6152.                         continue;
  6153.                     }
  6154.                     $availableStockItems = $productRepository->getAvailableStockItems($product);
  6155.                     $image = '';
  6156.                     $images = '';
  6157.                     if ($environment == 'prod') {
  6158.                         $photos = $product->getAlbum()->getPhotos();
  6159.                         if (count($photos) > 0) {
  6160.                             $photos = Collections::sort($photos);
  6161.                             foreach ($photos as $photo) {
  6162.                                 if (is_object($photo)) {
  6163.                                     if ($image == '') {
  6164.                                         $image = $this->getImage($photo, 'product/' . $product->getCode(), true)->resize(Image::PRODUCT_VIEW_THUMB_WIDTH, Image::PRODUCT_VIEW_THUMB_HEIGHT);
  6165.                                     } else {
  6166.                                         $images .= '<IMAGE_URL>' . $this->getImage($photo, 'product/' . $product->getCode(), true)->resize(Image::PRODUCT_VIEW_THUMB_WIDTH, Image::PRODUCT_VIEW_THUMB_HEIGHT) . '</IMAGE_URL>';
  6167.                                     }
  6168.                                 }
  6169.                             }
  6170.                         }
  6171.                     }
  6172.                     if ($productMeta->getDomainVatSuggestedPrice() != 0) {
  6173.                         $suggestedVatPrice = $productMeta->getDomainVatSuggestedPrice();
  6174.                     } else {
  6175.                         $suggestedPrice = $this->calculateSuggestedPrice($productMeta);
  6176.                         $suggestedVatPrice = $domain->createVatPrice($suggestedPrice);
  6177.                     }
  6178.                     $subCategories = '<SUB_CATEGORIES>';
  6179.                     foreach ($product->getBadges() as $badge) {
  6180.                         if ($badge != 'win10') {
  6181.                             $subCategories .= '<SUB_CAT>' . ucfirst($badge) . '</SUB_CAT>';
  6182.                         }
  6183.                     }
  6184.                     $subCategories .= '</SUB_CATEGORIES>';
  6185.                     $created = $product->getCreated()->format('Y-m-d, H:i');
  6186.                     $updated = !is_null($product->getUpdated()) ? $product->getUpdated()->format('Y-m-d, H:i') : '-';
  6187.                     $productType = $product->getType();
  6188.                     $categoryValue = trim($productType->getTitle());
  6189.                     $categoryPageWithParent = $productType->getCategoryPageWithParentByDomain($requestDomain);
  6190.                     $parentCategoryTitle = "<FULL_CATEGORY>";
  6191.                     if ($categoryPageWithParent) {
  6192.                         $parentCategoryId = $categoryPageWithParent->getParentCategory()->getId();
  6193.                         if (!isset($categoryPageTitles[$parentCategoryId])) {
  6194.                             $pageInfo = $entityManager->getRepository(PageMeta::class)->findOneBy([
  6195.                                 'categoryPage' => $parentCategoryId,
  6196.                                 'language' => $language->getId(),
  6197.                             ]);
  6198.                             $categoryPageTitles[$parentCategoryId] = $translator->trans(trim($pageInfo->getTitle()));
  6199.                             if ($pageInfo) {
  6200.                                 $categoryPageTitles[$parentCategoryId] = $translator->trans(trim($pageInfo->getTitle()));
  6201.                             }
  6202.                         }
  6203.                         $categoryValue = $translator->trans($categoryValue);
  6204.                         if (isset($categoryPageTitles[$parentCategoryId])) {
  6205.                             $parentCategoryTitle .= $categoryPageTitles[$parentCategoryId] . " | " . $categoryValue;
  6206.                         } else {
  6207.                             $parentCategoryTitle .= $categoryValue;
  6208.                         }
  6209.                     }
  6210.                     $parentCategoryTitle .= "</FULL_CATEGORY>";
  6211.                     if ($parentCategoryTitle == "<FULL_CATEGORY></FULL_CATEGORY>") {
  6212.                         $categoryValue = $translator->trans($categoryValue);
  6213.                         $parentCategoryTitle = "<FULL_CATEGORY>" . $categoryValue . "</FULL_CATEGORY>";
  6214.                     }
  6215.                     $ean = '';
  6216.                     if (!is_null($product->getEan()) && $product->getEan() != '') {
  6217.                         $ean = $product->getEan();
  6218.                     }
  6219.                     if (count($availableStockItems) > 0 && $product->getQualityStatus() == Product::QualityStatus_Bazaar) {
  6220.                         /**
  6221.                          * @var StockItem $stockItem
  6222.                          */
  6223.                         foreach ($availableStockItems as $stockItem) {
  6224.                             if ($stockItem->getAlbum() && $stockItem->getAlbum()->getPhotos()->count() > 0) {
  6225.                                 foreach ($stockItem->getAlbum()->getPhotos() as $stockItemPhoto) {
  6226.                                     $images .= '<IMAGE_URL>' . $this->getImage(
  6227.                                         $stockItemPhoto,
  6228.                                         'product/' . $product->getCode(),
  6229.                                         true
  6230.                                     )->resize(
  6231.                                         Image::PRODUCT_VIEW_THUMB_WIDTH,
  6232.                                         Image::PRODUCT_VIEW_THUMB_HEIGHT
  6233.                                     ) . '</IMAGE_URL>';
  6234.                                 }
  6235.                             }
  6236.                             $identifier = '';
  6237.                             if (!is_null($stockItem->getAikenCode()) && $stockItem->getAikenCode() != '') {
  6238.                                 $identifier = $stockItem->getAikenCode();
  6239.                             }
  6240.                             if ($identifier != '' && !is_null(
  6241.                                 $stockItem->getSerialNumber()
  6242.                             ) && $stockItem->getSerialNumber() != '') {
  6243.                                 $identifier = $stockItem->getSerialNumber();
  6244.                             }
  6245.                             if ($identifier == '') {
  6246.                                 continue;
  6247.                             }
  6248.                             $xml .= "<SHOPITEM>
  6249.                             <ITEM_ID>" . $product->getId() . "-" . $identifier . "</ITEM_ID>
  6250.                             <CODE>" . $product->getCode() . "-" . $identifier . "</CODE>
  6251.                             <EAN>" . $ean . "</EAN>
  6252.                             <NAME><![CDATA[" . $product->getFullTitle($translator) . "]]></NAME>
  6253.                             <VENDOR><![CDATA[" . $product->getVendor()->getName() . "]]></VENDOR>
  6254.                             <SHORT_DESCRIPTION><![CDATA[" . $product->getDescription() . "]]></SHORT_DESCRIPTION>
  6255.                             <DESCRIPTION><![CDATA[" . preg_replace(
  6256.                                 '#<[^>]+>#',
  6257.                                 ' ',
  6258.                                 $productMeta->getFullDescription($translator)
  6259.                             ) . "]]></DESCRIPTION>
  6260.                             <IMAGE_URL>" . $image . "</IMAGE_URL>
  6261.                             <PRODUCT_URL>" . $seoUrlHelper->link('product', [
  6262.                                 'product_id' => $product->getId(), 
  6263.                                 'isBazaar'   => $product->isBazaar()
  6264.                             ]) . "</PRODUCT_URL>
  6265.                             <PRICE>" . $price . "</PRICE>
  6266.                             <ORIGINAL_PRICE>" . $originalPrice . "</ORIGINAL_PRICE>
  6267.                             <SUGGESTED_PRICE>" . $suggestedVatPrice . "</SUGGESTED_PRICE>
  6268.                             <CATEGORY>$categoryValue</CATEGORY>
  6269.                             " . $parentCategoryTitle . "
  6270.                             " . $subCategories . "
  6271.                             <QUALITY>" . $this->getTranslator()->trans(
  6272.                                 strtolower($qualityStatuses[$product->getQualityStatus()])
  6273.                             ) . "</QUALITY>
  6274.                             <IN_STOCK>1</IN_STOCK>
  6275.                             <CREATED>" . $created . "</CREATED>
  6276.                             <UPDATED>" . $updated . "</UPDATED>
  6277.                             <IMAGES>" . $images . "</IMAGES>";
  6278.                             if ($product->getWeight() > 0) {
  6279.                                 $xml .= "<Suly>" . number_format($product->getWeight() / 1000, 2, '.', '') . "</Suly>";
  6280.                             }
  6281.                             foreach ($product->getSpecificationProductAttributeOptions() as $pao) {
  6282.                                 $ao = $pao->getOption();
  6283.                                 if ($ao->getAttribute()->getId() == 95) {
  6284.                                     continue;
  6285.                                 }
  6286.                                 if (!isset($attrTitles[$ao->getAttribute()->getId()])) {
  6287.                                     $attrTitles[$ao->getAttribute()->getId()] = $ao->getAttribute()->getTitle(
  6288.                                         $translator
  6289.                                     );
  6290.                                 }
  6291.                                 $attrTitle = $attrTitles[$ao->getAttribute()->getId()];
  6292.                                 if (!isset($attrOptTitles[$ao->getId()])) {
  6293.                                     $attrOptTitles[$ao->getId()] = $ao->getTitle($translator);
  6294.                                 }
  6295.                                 $attrOptTitle = $attrOptTitles[$ao->getId()];
  6296.                                 $attributeTitle = $this->removeSpecialCharacters($attrTitle);
  6297.                                 if ($attributeTitle != '') {
  6298.                                     $xml .= "<" . $attributeTitle . ">" . str_replace(
  6299.                                         '&',
  6300.                                         '&amp;',
  6301.                                         $attrOptTitle
  6302.                                     ) . "</" . $attributeTitle . ">";
  6303.                                 }
  6304.                             }
  6305.                             $xml .= '<TERMEKHIBA>';
  6306.                             if (!is_null($stockItem->getErrorCodes()) && $stockItem->getErrorCodes() != '') {
  6307.                                 $errors = '';
  6308.                                 foreach (explode(' ', $stockItem->getErrorCodes()) as $errorCode) {
  6309.                                     if ($errors != '') {
  6310.                                         $errors .= ', ';
  6311.                                     }
  6312.                                     if (isset($errorCodeCache[$errorCode])) {
  6313.                                         $errors .= $errorCodeCache[$errorCode];
  6314.                                         continue;
  6315.                                     }
  6316.                                     $errorCodeEntity = $entityManager->getRepository(ErrorCode::class)->findOneByCode(
  6317.                                         $errorCode
  6318.                                     );
  6319.                                     if ($errorCodeEntity) {
  6320.                                         $errorCodeCache[$errorCode] = $errorCodeEntity->getHuText();
  6321.                                         $errors .= $errorCodeEntity->getHuText();
  6322.                                     }
  6323.                                 }
  6324.                                 $xml .= $errors;
  6325.                             }
  6326.                             $xml .= '</TERMEKHIBA>';
  6327.                             $xml .= "</SHOPITEM>\n";
  6328.                         }
  6329.                     } else {
  6330.                         $xml .= "<SHOPITEM>
  6331.                             <ITEM_ID>" . $product->getId() . "</ITEM_ID>
  6332.                             <CODE>" . $product->getCode() . "</CODE>
  6333.                             <EAN>" . $ean . "</EAN>
  6334.                             <NAME><![CDATA[" . $product->getFullTitle($translator) . "]]></NAME>
  6335.                             <VENDOR><![CDATA[" . $product->getVendor()->getName() . "]]></VENDOR>
  6336.                             <SHORT_DESCRIPTION><![CDATA[" . $product->getDescription() . "]]></SHORT_DESCRIPTION>
  6337.                             <DESCRIPTION><![CDATA[" . preg_replace(
  6338.                             '#<[^>]+>#',
  6339.                             ' ',
  6340.                             $productMeta->getFullDescription($translator)
  6341.                         ) . "]]></DESCRIPTION>
  6342.                             <IMAGE_URL>" . $image . "</IMAGE_URL>
  6343.                             <PRODUCT_URL>" . $seoUrlHelper->link('product', [
  6344.                             'product_id' => $product->getId(),
  6345.                             'isBazaar'   => $product->isBazaar()
  6346.                         ]) . "</PRODUCT_URL>
  6347.                             <PRICE>" . $price . "</PRICE>
  6348.                             <ORIGINAL_PRICE>" . $originalPrice . "</ORIGINAL_PRICE>
  6349.                             <SUGGESTED_PRICE>" . $suggestedVatPrice . "</SUGGESTED_PRICE>
  6350.                             <CATEGORY>$categoryValue</CATEGORY>
  6351.                             " . $parentCategoryTitle . "
  6352.                             " . $subCategories . "
  6353.                             <QUALITY>" . $this->getTranslator()->trans(
  6354.                             strtolower($qualityStatuses[$product->getQualityStatus()])
  6355.                         ) . "</QUALITY>
  6356.                             <IN_STOCK>" . $product->getAvailable() . "</IN_STOCK>
  6357.                             <CREATED>" . $created . "</CREATED>
  6358.                             <UPDATED>" . $updated . "</UPDATED>
  6359.                             <IMAGES>" . $images . "</IMAGES>";
  6360.                         if ($product->getWeight() > 0) {
  6361.                             $xml .= "<Suly>" . number_format($product->getWeight() / 1000, 2, '.', '') . "</Suly>";
  6362.                         }
  6363.                         foreach ($product->getSpecificationProductAttributeOptions() as $pao) {
  6364.                             $ao = $pao->getOption();
  6365.                             if ($ao->getAttribute()->getId() == 95) {
  6366.                                 continue;
  6367.                             }
  6368.                             if (!isset($attrTitles[$ao->getAttribute()->getId()])) {
  6369.                                 $attrTitles[$ao->getAttribute()->getId()] = $ao->getAttribute()->getTitle(
  6370.                                     $translator
  6371.                                 );
  6372.                             }
  6373.                             $attrTitle = $attrTitles[$ao->getAttribute()->getId()];
  6374.                             if (!isset($attrOptTitles[$ao->getId()])) {
  6375.                                 $attrOptTitles[$ao->getId()] = $ao->getTitle($translator);
  6376.                             }
  6377.                             $attrOptTitle = $attrOptTitles[$ao->getId()];
  6378.                             $attributeTitle = $this->removeSpecialCharacters($attrTitle);
  6379.                             if ($attributeTitle != '') {
  6380.                                 $xml .= "<" . $attributeTitle . ">" . str_replace(
  6381.                                     '&',
  6382.                                     '&amp;',
  6383.                                     $attrOptTitle
  6384.                                 ) . "</" . $attributeTitle . ">";
  6385.                             }
  6386.                         }
  6387.                         $xml .= "</SHOPITEM>\n";
  6388.                     }
  6389.                 }
  6390.                 $xml .= '</SHOP>';
  6391.                 $cacheItem->set($xml);
  6392.                 $cacheItem->expiresAfter(self::CACHE_LIFETIME_4_HOUR);
  6393.                 $cache->save($cacheItem);
  6394.             }
  6395.             $entityManager->flush();
  6396.             $response = new Response($xml);
  6397.             $response->headers->set('Content-Type', 'xml');
  6398.             return $response;
  6399.         }
  6400.         return new Response('Something went wrong, please contact your sales manager!');
  6401.     }
  6402.     /**
  6403.      * @return int[]
  6404.      */
  6405.     private function getAccessoriesProductTypeIdList(): array
  6406.     {
  6407.         return [
  6408.             4,
  6409.             5,
  6410.             6,
  6411.             7,
  6412.             8,
  6413.             9,
  6414.             10,
  6415.             11,
  6416.             12,
  6417.             13,
  6418.             20,
  6419.             22,
  6420.             23,
  6421.             32,
  6422.             33,
  6423.             34,
  6424.             45,
  6425.             55,
  6426.             56,
  6427.             64,
  6428.             65,
  6429.             70,
  6430.             71,
  6431.             72,
  6432.             85,
  6433.             86,
  6434.             103,
  6435.             110,
  6436.             113,
  6437.             114,
  6438.             124,
  6439.             125,
  6440.             145,
  6441.             146,
  6442.             147,
  6443.             149,
  6444.             150,
  6445.             151,
  6446.             152,
  6447.             154,
  6448.             155,
  6449.             156,
  6450.             160,
  6451.             166,
  6452.             167,
  6453.             168,
  6454.             174,
  6455.             180,
  6456.             181,
  6457.             182,
  6458.             184,
  6459.             185,
  6460.             186,
  6461.             187,
  6462.             192,
  6463.             193,
  6464.             198,
  6465.             202,
  6466.         ];
  6467.     }
  6468.     /**
  6469.      * @Route("/partner-product-list-download", name="product_partner_product_list_download", defaults={"_locale":""})
  6470.      * @param Request $request
  6471.      * @return Response
  6472.      * @throws \Psr\SimpleCache\InvalidArgumentException
  6473.      */
  6474.     public function partnerProductListDownloadAction(Request $request): Response
  6475.     {
  6476.         $multistorHelper = $this->getMultiStoreHelper($request);
  6477.         if ($multistorHelper->getCustomerTypeId() != MultiStore::CUSTOMER_TYPE_WHOLESALE) {
  6478.             return new Response('Permission denied!');
  6479.         }
  6480.         $domain = $multistorHelper->getDomain();
  6481.         $domainId = $domain->getId();
  6482.         $currency = $this->getCurrencyISOForm($domain->getCurrency());
  6483.         $entityManager = $this->getEntityManager();
  6484.         $cache = $this->cache;
  6485.         $cacheKeyOutputKey = 'partner.product.list.2021.' . $domain->getLanguage()->getCode();
  6486.         $cacheKeyOutput = $cache->getItem($cacheKeyOutputKey);
  6487.         $cacheKeyFilenameKey = 'partner.product.list.2021.' . $domain->getLanguage()->getCode() . '.filename';
  6488.         $cacheKeyFilename = $cache->getItem($cacheKeyFilenameKey);
  6489.         $cacheLastProductListUpdateKey = 'partner.product.list.last_update';
  6490.         $cacheLastProductListUpdate = $cache->getItem($cacheLastProductListUpdateKey);
  6491.         if (!$cacheKeyOutput->isHit() || !$cacheKeyFilename->isHit()) {
  6492.             $products = $entityManager->createQuery("SELECT p
  6493.               FROM AtechNetCoreBundle:Product p
  6494.               LEFT JOIN AtechNetCoreBundle:ProductMeta pm WITH pm.product = p.id AND pm.domain = " . $domainId . "
  6495.               WHERE p.archived = 0 AND p.available > 0 AND pm.active = 1 AND pm.orderable = 1 AND p.qualityStatus != " . Product::QualityStatus_Bazaar . "
  6496.               ORDER BY p.code ASC")
  6497.                 ->getResult();
  6498.             $attributes = $entityManager->createQuery("SELECT DISTINCT(a.id) as id, a.title
  6499.               FROM AtechNetCoreBundle:Attribute a
  6500.               LEFT JOIN a.options ao
  6501.               LEFT JOIN ao.productAttributes pa
  6502.               LEFT JOIN pa.product p
  6503.               LEFT JOIN AtechNetCoreBundle:ProductMeta pm WITH pm.product = p.id AND pm.domain = " . $domainId . "
  6504.               WHERE a.type = 'conf' AND p.archived = 0 AND p.available > 0 AND pm.active = 1 AND pm.orderable = 1
  6505.               ORDER BY a.id ASC")
  6506.                 ->getResult();
  6507.             $attributeTitles = '';
  6508.             foreach ($attributes as $a) {
  6509.                 $attributeTitles .= '<th>' . $a['title'] . '</th>';
  6510.             }
  6511.             $output = '<table>
  6512.                 <tr>
  6513.                     <th colspan="6">Generated: ' . (new \DateTime())->format('d.m.Y, H:i:s') . '</th>
  6514.                 </tr>
  6515.                 <tr>
  6516.                     <th>Code</th>
  6517.                     <th>Type</th>
  6518.                     <th>Brand</th>
  6519.                     <th width="200">Name</th>
  6520.                     <th>Quality</th>
  6521.                     <th>Config</th>
  6522.                     <th>In stock</th>
  6523.                     <th>Price [' . $currency . ']</th>
  6524.                     <th>Price + VAT [' . $currency . ']</th>
  6525.                     <th>Suggested price [' . $currency . ']</th>
  6526.                     <th>Suggested price + VAT [' . $currency . ']</th>
  6527.                     ' . $attributeTitles . '
  6528.                 </tr>';
  6529.             /**
  6530.              * @var Product $product
  6531.              */
  6532.             foreach ($products as $product) {
  6533.                 $productMeta = $product->getDomainMeta($domain);
  6534.                 $output .= '<tr>
  6535.                     <td>' . $product->getCode() . '</td>
  6536.                     <td>' . $product->getType()->getTitle() . '</td>
  6537.                     <td>' . $product->getVendor()->getName() . '</td>
  6538.                     <td width="200">' . $product->getName() . '</td>
  6539.                     <td>' . $product->getQualityStatusTitle($product->getQualityStatus()) . '</td>
  6540.                     <td>' . $product->getDescription() . '</td>
  6541.                     <td>' . $product->getAvailable() . '</td>
  6542.                     <td>' . ($productMeta->isDiscounted() ? $productMeta->getDomainDiscount() : $productMeta->getDomainPrice()) . '</td>
  6543.                     <td>' . ($productMeta->isDiscounted() ? $productMeta->getDomainVatDiscount() : $productMeta->getDomainVatPrice()) . '</td>
  6544.                     <td>' . $productMeta->getDomainSuggestedPrice() . '</td>
  6545.                     <td>' . $productMeta->getDomainVatSuggestedPrice() . '</td>
  6546.                     ' . $this->createPartnerDownloadListAttributesForProduct($product, $attributes) . '
  6547.                 </tr>';
  6548.             }
  6549.             $output .= '</table>';
  6550.             $filename = 'furbify_partner_product_export_' . $domain->getLanguage()->getCode() . '_' . date('Ymd-His') . '.xls';
  6551.             $cacheKeyOutput->set($output);
  6552.             $cacheKeyOutput->expiresAfter(self::CACHE_LIFETIME_1_HOUR);
  6553.             $cache->save($cacheKeyOutput);
  6554.             $cacheKeyFilename->set($filename);
  6555.             $cacheKeyFilename->expiresAfter(self::CACHE_LIFETIME_1_HOUR);
  6556.             $cache->save($cacheKeyFilename);
  6557.             $cacheLastProductListUpdate->set((new \DateTime())->format('d.m.Y, H:i'));
  6558.             $cacheLastProductListUpdate->expiresAfter(self::CACHE_LIFETIME_1_HOUR);
  6559.             $cache->save($cacheLastProductListUpdate);
  6560.         } else {
  6561.             $output = $cache->getItem($cacheKeyOutputKey)->get();
  6562.             $filename = $cache->getItem($cacheKeyFilenameKey)->get();
  6563.         }
  6564.         $response = new Response();
  6565.         $response->headers->set('Content-Encoding', 'UTF-8');
  6566.         $response->headers->set('Content-Type', 'application/vnd.ms-excel');
  6567.         $response->headers->set('Content-Disposition', 'attachment;filename="' . $filename);
  6568.         $response->setContent($output);
  6569.         return $response;
  6570.     }
  6571.     /**
  6572.      * @Route("/partner-unas-product-list-download", name="product_partner_unas_product_list_download", defaults={"_locale":""})
  6573.      * @param Request $request
  6574.      * @return Response
  6575.      * @throws \Psr\SimpleCache\InvalidArgumentException
  6576.      */
  6577.     public function partnerUnasProductListDownloadAction(Request $request): Response
  6578.     {
  6579.         $multistoreHelper = $this->getMultiStoreHelper($request);
  6580.         if ($multistoreHelper->getCustomerTypeId() != MultiStore::CUSTOMER_TYPE_WHOLESALE) {
  6581.             return new Response('Permission denied!');
  6582.         }
  6583.         $domain = $multistoreHelper->getDomain();
  6584.         $domainId = $domain->getId();
  6585.         $entityManager = $this->getEntityManager();
  6586.         $translator = new DatabaseTranslator($entityManager, $domain->getId());
  6587.         $cache = $this->cache;
  6588.         $cacheKeyOutputKey = 'partner.unas.product.list.' . date('Y') . '.' . $domain->getLanguage()->getCode();
  6589.         $cacheKeyOutput = $cache->getItem($cacheKeyOutputKey);
  6590.         $cacheKeyFilenameKey = 'partner.unas.product.list.' . date('Y') . '.' . $domain->getLanguage()->getCode() . '.filename';
  6591.         $cacheKeyFilename = $cache->getItem($cacheKeyFilenameKey);
  6592.         $cacheLastProductListUpdateKey = 'partner.unas.product.list.last-update';
  6593.         $cacheLastProductListUpdate = $cache->getItem($cacheLastProductListUpdateKey);
  6594.         if (!$cacheKeyOutput->isHit() || !$cacheKeyFilename->isHit()) {
  6595.             // UTF-8 BOM
  6596.             $output = "\xEF\xBB\xBF";
  6597.             // Header
  6598.             $header = [
  6599.                 'Cikkszám',
  6600.                 'Termék Név',
  6601.                 'Státusz',
  6602.                 'Nettó Ár',
  6603.                 'Bruttó Ár',
  6604.                 'Kategória',
  6605.                 'Rövid Leírás',
  6606.                 'Tulajdonságok',
  6607.                 'Min. Menny.',
  6608.                 'Max. Menny.',
  6609.                 'Raktárkészlet',
  6610.                 'Egység',
  6611.                 'Kép link',
  6612.             ];
  6613.             $output .= '"' . implode('";"', $header) . '"' . PHP_EOL;
  6614.             // Products
  6615.             $products = $entityManager->createQuery("SELECT p
  6616.                 FROM AtechNetCoreBundle:Product p
  6617.                 LEFT JOIN AtechNetCoreBundle:ProductMeta pm WITH pm.product = p.id AND pm.domain = " . $domainId . "
  6618.                 WHERE p.archived = 0 AND p.available > 0 AND pm.active = 1 AND pm.orderable = 1 AND p.qualityStatus != " . Product::QualityStatus_Bazaar . " 
  6619.                 ORDER BY p.code ASC")
  6620.                 ->getResult();
  6621.             foreach ($products as $product) {
  6622.                 // Categories
  6623.                 $categories = [];
  6624.                 $mainCategory = '';
  6625.                 if ($product->getCategoryPages()->count() > 0) {
  6626.                     foreach ($product->getCategoryPages() as $categoryPage) {
  6627.                         if ($categoryPage->isPublished() && $categoryPage->getDomain()->getId() == $multistoreHelper->getRetailDomainByWholesaleDomain()->getId()) {
  6628.                             // Category
  6629.                             $category = '';
  6630.                             if ($categoryPage->getParentCategory()) {
  6631.                                 if ($categoryPage->getParentCategory()->getParentCategory()) {
  6632.                                     $categoryMeta = $categoryPage->getParentCategory()->getParentCategory()->getMetaByLanguage($domain->getLanguage());
  6633.                                     if ($categoryMeta) {
  6634.                                         $category .= $categoryMeta->getTitle();
  6635.                                     }
  6636.                                 }
  6637.                                 $categoryMeta = $categoryPage->getParentCategory()->getMetaByLanguage($domain->getLanguage());
  6638.                                 if ($categoryMeta) {
  6639.                                     $category .= ($category !== '' ? '|' : '') . $categoryMeta->getTitle();
  6640.                                 }
  6641.                             }
  6642.                             $categoryMeta = $categoryPage->getMetaByLanguage($domain->getLanguage());
  6643.                             if ($categoryMeta) {
  6644.                                 $category .= ($category !== '' ? '|' : '') . $categoryMeta->getTitle();
  6645.                             }
  6646.                             if ($category !== '') {
  6647.                                 $categories[] = $category;
  6648.                             }
  6649.                         }
  6650.                     }
  6651.                 }
  6652.                 if ($product->getType()->getCategoryPages()->count() > 0) {
  6653.                     foreach ($product->getType()->getCategoryPages() as $categoryPage) {
  6654.                         // The product falls into this category
  6655.                         $add = false;
  6656.                         if ($categoryPage->isPublished() && $categoryPage->getDomain()->getId() == $multistoreHelper->getRetailDomainByWholesaleDomain()->getId()) {
  6657.                             // Check by Vendor
  6658.                             foreach ($categoryPage->getVendors() as $vendor) {
  6659.                                 if ($vendor->getId() == $product->getVendor()->getId()) {
  6660.                                     $add = true;
  6661.                                     break;
  6662.                                 }
  6663.                             }
  6664.                             // Check by Badge
  6665.                             if ($categoryPage->getBadges()) {
  6666.                                 $badges = json_decode($categoryPage->getBadges());
  6667.                                 foreach ($badges as $badge) {
  6668.                                     if (in_array($badge, $product->getBadges())) {
  6669.                                         $add = true;
  6670.                                         break;
  6671.                                     }
  6672.                                 }
  6673.                             }
  6674.                             // Main Category
  6675.                             if ($categoryPage->getVendors()->count() == 0 && $categoryPage->getBadges() == '') {
  6676.                                 $add = true;
  6677.                             }
  6678.                         }
  6679.                         // Add
  6680.                         if ($add) {
  6681.                             // Category Tree
  6682.                             $category = '';
  6683.                             if ($categoryPage->getParentCategory()) {
  6684.                                 if ($categoryPage->getParentCategory()->getParentCategory()) {
  6685.                                     $categoryMeta = $categoryPage->getParentCategory()->getParentCategory()->getMetaByLanguage($domain->getLanguage());
  6686.                                     if ($categoryMeta) {
  6687.                                         $category .= $categoryMeta->getTitle();
  6688.                                     }
  6689.                                 }
  6690.                                 $categoryMeta = $categoryPage->getParentCategory()->getMetaByLanguage($domain->getLanguage());
  6691.                                 if ($categoryMeta) {
  6692.                                     $category .= ($category !== '' ? '|' : '') . $categoryMeta->getTitle();
  6693.                                 }
  6694.                             }
  6695.                             $categoryMeta = $categoryPage->getMetaByLanguage($domain->getLanguage());
  6696.                             if ($categoryMeta) {
  6697.                                 $category .= ($category !== '' ? '|' : '') . $categoryMeta->getTitle();
  6698.                             }
  6699.                             if ($category !== '') {
  6700.                                 $categories[] = $category;
  6701.                             }
  6702.                         }
  6703.                     }
  6704.                 }
  6705.                 if (!empty($categories)) {
  6706.                     foreach ($categories as $category) {
  6707.                         if (mb_strlen($category) > mb_strlen($mainCategory)) {
  6708.                             $mainCategory = $category;
  6709.                         }
  6710.                     }
  6711.                 }
  6712.                 // Attributes
  6713.                 $attributes = '';
  6714.                 if ($product->getVendor()->getName()) {
  6715.                     $attributes .= '<tr><td>' . $this->getTranslator()->trans('Brand') . '</td><td>' . $product->getVendor()->getName() . '</td></tr>';
  6716.                 }
  6717.                 foreach ($product->getSpecificationAttributeOptions() as $attributeOption) {
  6718.                     $attributes .= '<tr><td>' . $attributeOption->getAttribute()->getTitle($translator) . '</td><td>' . addslashes(($attributeOption->getLongTitle() == '' ? $attributeOption->getTitle($translator) : $attributeOption->getLongTitle($translator))) . '</td></tr>';
  6719.                 }
  6720.                 if ($attributes) {
  6721.                     $attributes = '<!HTML KOD><table>' . $attributes . '</table>';
  6722.                 }
  6723.                 $productMeta = $product->getDomainMeta($domain);
  6724.                 // Image
  6725.                 $image = '';
  6726.                 if (count($product->getAlbum()->getPhotos()) > 0) {
  6727.                     foreach ($product->getAlbum()->getPhotos() as $photo) {
  6728.                         $image = $this->getImage($photo, 'product/' . $product->getCode(), true)->resize(Image::PRODUCT_VIEW_POPUP_WIDTH, Image::PRODUCT_VIEW_POPUP_HEIGHT);
  6729.                         break;
  6730.                     }
  6731.                 }
  6732.                 if ($mainCategory !== '') {
  6733.                     $data = [
  6734.                         $product->getCode(),
  6735.                         addslashes($product->getName()),
  6736.                         1,
  6737.                         number_format($productMeta->getDomainVatSuggestedPrice() / (1 + ($domain->getVat() / 100)), 3, '.', ''),
  6738.                         $productMeta->getDomainVatSuggestedPrice(),
  6739.                         $mainCategory,
  6740.                         addslashes($product->getDescription()),
  6741.                         $attributes,
  6742.                         1,
  6743.                         '',
  6744.                         $product->getAvailable(),
  6745.                         $this->getTranslator()->trans('pc'),
  6746.                         $image,
  6747.                     ];
  6748.                     $output .= '"' . implode('";"', $data) . '"' . PHP_EOL;
  6749.                 }
  6750.             }
  6751.             $filename = 'furbify-partner-unas-product-export-' . $domain->getLanguage()->getCode() . '-' . date('Ymd-His') . '.csv';
  6752.             $cacheKeyOutput->set($output);
  6753.             $cacheKeyOutput->expiresAfter(self::CACHE_LIFETIME_1_HOUR);
  6754.             $cache->save($cacheKeyOutput);
  6755.             $cacheKeyFilename->set($filename);
  6756.             $cacheKeyFilename->expiresAfter(self::CACHE_LIFETIME_1_HOUR);
  6757.             $cache->save($cacheKeyFilename);
  6758.             $cacheLastProductListUpdate->set((new \DateTime())->format('d.m.Y, H:i'));
  6759.             $cacheLastProductListUpdate->expiresAfter(self::CACHE_LIFETIME_1_HOUR);
  6760.             $cache->save($cacheLastProductListUpdate);
  6761.         } else {
  6762.             $output = $cacheKeyOutput->get();
  6763.             $filename = $cacheKeyFilename->get();
  6764.         }
  6765.         $response = new Response();
  6766.         $response->headers->set('Content-Type', 'text/csv;charset=utf-8');
  6767.         $response->headers->set('Content-Disposition', 'attachment;filename="' . $filename);
  6768.         $response->setContent($output);
  6769.         return $response;
  6770.     }
  6771.     /**
  6772.      * @param Product $product
  6773.      * @param $attributes
  6774.      * @return string
  6775.      */
  6776.     private function createPartnerDownloadListAttributesForProduct(Product $product, $attributes): string
  6777.     {
  6778.         $attributesOutput = '';
  6779.         $productattributesArray = [];
  6780.         /**
  6781.          * @var AttributeOption $ao
  6782.          */
  6783.         foreach ($product->getSpecificationAttributeOptions() as $ao) {
  6784.             $productattributesArray[$ao->getAttribute()->getId()] = $ao->getLongTitle() == '' ? $ao->getTitle() : $ao->getLongTitle();
  6785.         }
  6786.         foreach ($attributes as $attr) {
  6787.             if (isset($productattributesArray[$attr['id']])) {
  6788.                 $attributesOutput .= '<td>' . $productattributesArray[$attr['id']] . '</td>';
  6789.             } else {
  6790.                 $attributesOutput .= '<td></td>';
  6791.             }
  6792.         }
  6793.         return $attributesOutput;
  6794.     }
  6795.     /**
  6796.      * @param ProductMeta $productMeta
  6797.      * @return int
  6798.      */
  6799.     private function calculateSuggestedPrice(ProductMeta $productMeta): int
  6800.     {
  6801.         $product = $productMeta->getProduct();
  6802.         $productTypeId = $product->getType()->getId();
  6803.         $sellingPrice = $productMeta->isDiscounted() ? $productMeta->getDiscount() : $productMeta->getPrice();
  6804.         if ($productTypeId == 52 || $productTypeId == 60) { // PC or NB
  6805.             $suggestedPrice = $sellingPrice < 150 ? $sellingPrice + 40 : $sellingPrice + 50;
  6806.         } elseif ($productTypeId == 44) { // Monitor
  6807.             $suggestedPrice = $sellingPrice < 60 ? $sellingPrice + 10 : $sellingPrice + 15;
  6808.         } else {
  6809.             $suggestedPrice = $sellingPrice < 10 ? $sellingPrice + 10 : $sellingPrice + 15;
  6810.         }
  6811.         return $suggestedPrice;
  6812.     }
  6813.     /**
  6814.      * @param CategoryPage $categoryPage
  6815.      * @param $productTypeId
  6816.      * @return bool
  6817.      */
  6818.     private function categoryHasProductType(CategoryPage $categoryPage, $productTypeId): bool
  6819.     {
  6820.         foreach ($categoryPage->getProductTypes() as $productType) {
  6821.             if ($productType->getId() == $productTypeId) {
  6822.                 return true;
  6823.             }
  6824.         }
  6825.         return false;
  6826.     }
  6827.     /**
  6828.      * @Route("/partner-label-download/{id}", name="product_partner_label_download", defaults={"_locale":""})
  6829.      * @param Request $request
  6830.      * @param int $id
  6831.      * @return \Symfony\Component\HttpFoundation\RedirectResponse|Response
  6832.      * @throws \Mpdf\MpdfException
  6833.      */
  6834.     public function productPriceLabelAction(Request $request, int $id)
  6835.     {
  6836.         $priceOnLabel = $request->request->get('print-label-price');
  6837.         if (!$this->getLoginHelper($request)->isLoggedIn()
  6838.             || $this->getCustomerTypeId($request) != MultiStore::CUSTOMER_TYPE_WHOLESALE
  6839.             || is_null($priceOnLabel)
  6840.             || !is_numeric($priceOnLabel)) {
  6841.             return $this->redirectToRoute('homepage');
  6842.         }
  6843.         $labelsWanted = [
  6844.             ProductType::PRODUCT_TYPE_ID_MONITOR => [
  6845.                 Attribute::ATTRIBUTE_ID_QUALITY,
  6846.                 Attribute::ATTRIBUTE_ID_SCREEN_SIZE,
  6847.                 Attribute::ATTRIBUTE_ID_MAXIMUM_RESOLUTION,
  6848.                 Attribute::ATTRIBUTE_ID_BRIGHTNESS,
  6849.                 Attribute::ATTRIBUTE_ID_CONTRAST,
  6850.                 Attribute::ATTRIBUTE_ID_RESPONSE_TIME,
  6851.                 Attribute::ATTRIBUTE_ID_VIEW_ANGLES,
  6852.                 Attribute::ATTRIBUTE_ID_ASPECT_RATIO,
  6853.                 Attribute::ATTRIBUTE_ID_GRAPHIC_INPUTS,
  6854.             ],
  6855.             ProductType::PRODUCT_TYPE_ID_NOTEBOOK => [
  6856.                 Attribute::ATTRIBUTE_ID_QUALITY,
  6857.                 Attribute::ATTRIBUTE_ID_CPU_NB,
  6858.                 Attribute::ATTRIBUTE_ID_RAM_NB,
  6859.                 Attribute::ATTRIBUTE_ID_SSD,
  6860.                 Attribute::ATTRIBUTE_ID_SSHD35,
  6861.                 Attribute::ATTRIBUTE_ID_HDD_25,
  6862.                 Attribute::ATTRIBUTE_ID_SCREEN_SIZE,
  6863.                 Attribute::ATTRIBUTE_ID_MAXIMUM_RESOLUTION,
  6864.                 Attribute::ATTRIBUTE_ID_VGA,
  6865.                 Attribute::ATTRIBUTE_ID_WEBCAM,
  6866.                 Attribute::ATTRIBUTE_ID_EXTERNAL_CONNECTORS,
  6867.                 Attribute::ATTRIBUTE_ID_OPERATING_SYSTEM,
  6868.             ],
  6869.             ProductType::PRODUCT_TYPE_ID_PC => [
  6870.                 Attribute::ATTRIBUTE_ID_QUALITY,
  6871.                 Attribute::ATTRIBUTE_ID_CPU_PC,
  6872.                 Attribute::ATTRIBUTE_ID_RAM_PC,
  6873.                 Attribute::ATTRIBUTE_ID_SSD,
  6874.                 Attribute::ATTRIBUTE_ID_SSHD35,
  6875.                 Attribute::ATTRIBUTE_ID_HDD_25,
  6876.                 Attribute::ATTRIBUTE_ID_HDD_35,
  6877.                 Attribute::ATTRIBUTE_ID_VGA,
  6878.                 Attribute::ATTRIBUTE_ID_FORM,
  6879.                 Attribute::ATTRIBUTE_ID_OPERATING_SYSTEM,
  6880.             ],
  6881.             ProductType::PRODUCT_TYPE_ID_PC_SET => [
  6882.                 Attribute::ATTRIBUTE_ID_QUALITY,
  6883.                 Attribute::ATTRIBUTE_ID_CPU_PC,
  6884.                 Attribute::ATTRIBUTE_ID_RAM_PC,
  6885.                 Attribute::ATTRIBUTE_ID_SSD,
  6886.                 Attribute::ATTRIBUTE_ID_SSHD35,
  6887.                 Attribute::ATTRIBUTE_ID_HDD_25,
  6888.                 Attribute::ATTRIBUTE_ID_HDD_35,
  6889.                 Attribute::ATTRIBUTE_ID_VGA,
  6890.                 Attribute::ATTRIBUTE_ID_FORM,
  6891.                 Attribute::ATTRIBUTE_ID_OPERATING_SYSTEM,
  6892.             ],
  6893.             ProductType::PRODUCT_TYPE_ID_ALL_IN_ONE => [
  6894.                 Attribute::ATTRIBUTE_ID_QUALITY,
  6895.                 Attribute::ATTRIBUTE_ID_CPU_PC,
  6896.                 Attribute::ATTRIBUTE_ID_RAM_PC,
  6897.                 Attribute::ATTRIBUTE_ID_SSD,
  6898.                 Attribute::ATTRIBUTE_ID_SSHD35,
  6899.                 Attribute::ATTRIBUTE_ID_HDD_25,
  6900.                 Attribute::ATTRIBUTE_ID_HDD_35,
  6901.                 Attribute::ATTRIBUTE_ID_VGA,
  6902.                 Attribute::ATTRIBUTE_ID_FORM,
  6903.                 Attribute::ATTRIBUTE_ID_OPERATING_SYSTEM,
  6904.             ],
  6905.             ProductType::PRODUCT_TYPE_ID_SMARTPHONE => [
  6906.                 Attribute::ATTRIBUTE_ID_QUALITY,
  6907.                 Attribute::ATTRIBUTE_ID_OPERATING_SYSTEM,
  6908.                 Attribute::ATTRIBUTE_ID_SCREEN_SIZE,
  6909.                 Attribute::ATTRIBUTE_ID_MAXIMUM_RESOLUTION,
  6910.                 Attribute::ATTRIBUTE_ID_CPU_PHONE,
  6911.                 Attribute::ATTRIBUTE_ID_DISPLAY,
  6912.                 Attribute::ATTRIBUTE_ID_RAM,
  6913.             ],
  6914.             ProductType::PRODUCT_TYPE_ID_SERVER => [
  6915.                 Attribute::ATTRIBUTE_ID_QUALITY,
  6916.                 Attribute::ATTRIBUTE_ID_CPU_PC,
  6917.                 Attribute::ATTRIBUTE_ID_RAM_PC,
  6918.                 Attribute::ATTRIBUTE_ID_SSD,
  6919.                 Attribute::ATTRIBUTE_ID_SSHD35,
  6920.                 Attribute::ATTRIBUTE_ID_HDD_25,
  6921.                 Attribute::ATTRIBUTE_ID_HDD_35,
  6922.                 Attribute::ATTRIBUTE_ID_VGA,
  6923.                 Attribute::ATTRIBUTE_ID_FORM,
  6924.             ],
  6925.             ProductType::PRODUCT_TYPE_ID_PROJECTOR => [
  6926.                 Attribute::ATTRIBUTE_ID_MAXIMUM_RESOLUTION,
  6927.                 Attribute::ATTRIBUTE_ID_ASPECT_RATIO,
  6928.                 Attribute::ATTRIBUTE_ID_CONTRAST,
  6929.                 Attribute::ATTRIBUTE_ID_PROJECTOR_REMOTE,
  6930.                 Attribute::ATTRIBUTE_ID_LUMEN,
  6931.             ],
  6932.             ProductType::PRODUCT_TYPE_ID_CPU => [
  6933.                 Attribute::ATTRIBUTE_ID_CPU_PC_FAMILY,
  6934.                 Attribute::ATTRIBUTE_ID_CPU_GENERATION,
  6935.                 Attribute::ATTRIBUTE_ID_CLOCKSPEED,
  6936.                 Attribute::ATTRIBUTE_ID_CPU_SOCKET,
  6937.             ],
  6938.             ProductType::PRODUCT_TYPE_ID_RAM_PC => [
  6939.                 Attribute::ATTRIBUTE_ID_MEMORY_TYPE,
  6940.                 Attribute::ATTRIBUTE_ID_MEMORY_SIZE,
  6941.                 Attribute::ATTRIBUTE_ID_MEMORY_FREQUENCY,
  6942.             ],
  6943.         ];
  6944.         $product = $this->getEntityManager()->getRepository(Product::class)->findOneById($id);
  6945.         if ($product) {
  6946.             $productHelper = $this->getProductHelper($request);
  6947.             $multistoreHelper = $this->getMultiStoreHelper($request);
  6948.             $domain = $multistoreHelper->getDomain();
  6949.             $currency = $domain->getCurrency();
  6950.             $productData = $productHelper->getStructuredDataForProduct($product);
  6951.             $labelAttributes = [];
  6952.             foreach ($labelsWanted[$productData['productTypeId']] as $labelWantedKey) {
  6953.                 foreach ($productData['attributes'] as $attributeKey => $attribute) {
  6954.                     if ($labelWantedKey == $attributeKey) {
  6955.                         $labelAttributes[$attributeKey]['title'] = $attribute['title'];
  6956.                         foreach ($attribute['options'] as $option) {
  6957.                             if (isset($labelAttributes[$attributeKey]['value'])) {
  6958.                                 $labelAttributes[$labelWantedKey]['value'] .= ', ';
  6959.                             } else {
  6960.                                 $labelAttributes[$labelWantedKey]['value'] = '';
  6961.                             }
  6962.                             $labelAttributes[$labelWantedKey]['value'] .= ($option['multiplier'] > 0 ? $option['multiplier'] . ' x ' : '') . $option['title'];
  6963.                         }
  6964.                     }
  6965.                 }
  6966.             }
  6967.             $productData['warrantyYear'] = $this->getWarrantyForProductType($domain->getId(), $productData['productTypeId'])['year'];
  6968.             $html = $this->getTwig()->render('AtechNetCoreBundle/PDF/productLabel.html.twig', [
  6969.                 'product' => $productData,
  6970.                 'currency' => $currency,
  6971.                 'labelAttributes' => $labelAttributes,
  6972.                 'priceOnLabel' => $priceOnLabel,
  6973.             ]);
  6974.             $defaultConfig = (new ConfigVariables())->getDefaults();
  6975.             $fontDirs = $defaultConfig['fontDir'];
  6976.             $defaultFontConfig = (new FontVariables())->getDefaults();
  6977.             $fontData = $defaultFontConfig['fontdata'];
  6978.             $pdf = new Mpdf([
  6979.                 'mode' => 'utf-8',
  6980.                 'format' => 'A6',
  6981.                 'default_font_size' => 9,
  6982.                 'fontDir' => array_merge($fontDirs, [
  6983.                     __DIR__ . '/../Resources/public/fonts',
  6984.                 ]),
  6985.                 'fontdata' => $fontData + [
  6986.                     'montserrat-normal' => [
  6987.                         'R' => 'Montserrat-Regular.ttf',
  6988.                     ],
  6989.                     'montserrat-bold' => [
  6990.                         'R' => 'Montserrat-ExtraBold.ttf',
  6991.                     ],
  6992.                 ],
  6993.                 'default_font' => 'montserrat-normal',
  6994.             ]);
  6995.             $pdf->shrink_tables_to_fit = true;
  6996.             $pdf->WriteHTML($html);
  6997.             return new Response(
  6998.                 $pdf->output(
  6999.                     $product->getCode() . '_' . (new \DateTime())->format('YmdHi') . '.pdf',
  7000.                     'I'
  7001.                 ),
  7002.                 Response::HTTP_OK,
  7003.                 [
  7004.                     'content-type' => 'application/pdf',
  7005.                 ]
  7006.             );
  7007.         }
  7008.         return $this->redirectToRoute('homepage');
  7009.     }
  7010.     /**
  7011.      * @Route("/prislusenstvo",                                     name="product_accessories_sk", defaults={"_locale":""})
  7012.      * @Route("/{_locale<%supported_locales%>?}/prislusenstvo",     name="product_accessories_sk_locale", defaults={"_locale":""})
  7013.      * @Route("/kiegeszitok",                                       name="product_accessories_hu", defaults={"_locale":""})
  7014.      * @Route("/{_locale<%supported_locales%>?}/kiegeszitok",       name="product_accessories_hu_locale", defaults={"_locale":""})
  7015.      * @Route("/prislusenstvi",                                     name="product_accessories_cz", defaults={"_locale":""})
  7016.      * @Route("/{_locale<%supported_locales%>?}/prislusenstvi",     name="product_accessories_cz_locale", defaults={"_locale":""})
  7017.      * @Route("/accessories",                                       name="product_accessories_en", defaults={"_locale":""})
  7018.      * @Route("/{_locale<%supported_locales%>?}/accessories",       name="product_accessories_en_locale", defaults={"_locale":""})
  7019.      * @Route("/pislusenstvi",                                      name="product_accessories_cz_to_redirect", defaults={"_locale":""})
  7020.      * @param Request $request
  7021.      * @return Response
  7022.      * @throws \Exception
  7023.      */
  7024.     public function accessoriesAction(Request $request): Response
  7025.     {
  7026.         $data = [];
  7027.         $translator = $this->getTranslator();
  7028.         if ($request->get('_route') == 'product_accessories_cz_to_redirect') {
  7029.             return $this->redirectToRoute('product_accessories_cz', [], 301);
  7030.         }
  7031.         $multiStore = $this->getMultiStoreHelper($request);
  7032.         $domain = $multiStore->getDomain();
  7033.         $cache = $this->cache;
  7034.         $cacheKey = 'accessories.page.v6.' . $domain->getId() . '.' . $request->getLocale();
  7035.         $cacheItem = $cache->getItem($cacheKey);
  7036.         if ($cacheItem->isHit()) {
  7037.             $data['sections'] = $cacheItem->get();
  7038.         } else {
  7039.             $entityManager = $this->getEntityManager();
  7040.             $productRepo = $entityManager->getRepository(Product::class);
  7041.             $seoUrlHelper = $this->getSeoUrlHelper($request);
  7042.             $productHelper = $this->getProductHelper($request);
  7043.             $data['sections'] = $productRepo->getAccessoriesSections($domain, $seoUrlHelper, $productHelper, $multiStore);
  7044.             $cacheItem->set($data['sections']);
  7045.             $cacheItem->expiresAfter(self::CACHE_LIFETIME_4_HOUR);
  7046.             $cache->save($cacheItem);
  7047.         }
  7048.         if (!empty($data['sections'])) {
  7049.             $data['seoTitle'] = $translator->trans('Accessories SEO title');
  7050.             $data['seoDescription'] = $translator->trans('Accessories SEO description');
  7051.             $data['canonical_link'] = '';
  7052.             $data['breadcrumbs'] = [
  7053.                 $this->getBreadCrumbsBase($request),
  7054.                 [
  7055.                     'text' => $translator->trans('Accessories'),
  7056.                     'href' => '',
  7057.                 ],
  7058.             ];
  7059.             $data['partnerLoginRedirect'] = false;
  7060.             if (!is_null($request->query->get('partner-link')) && $request->query->get('partner-link') == 1 && !$this->getLoginHelper($request)->isLoggedIn()) {
  7061.                 $data['partnerLoginRedirectRoute'] = $this->generateUrl('partner_login');
  7062.                 $data['partnerLoginRedirect'] = true;
  7063.             }
  7064.             $data['header'] = $this->getHeader($request);
  7065.             $data['footer'] = $this->getFooter($request);
  7066.             return $this->render('AtechNetCoreBundle/Product/parts.html.twig', $data);
  7067.         }
  7068.         return $this->forward('App\AtechNet\CoreBundle\Controller\DefaultController::notFoundAction');
  7069.     }
  7070.     /**
  7071.      * @Route("/egyeb-eszkozok",                                    name="product_other_categories_hu", defaults={"_locale":""})
  7072.      * @Route("/{_locale<%supported_locales%>?}/egyeb-eszkozok",    name="product_other_categories_hu_locale", defaults={"_locale":""})
  7073.      * @Route("/dalsie-kategorie",                                  name="product_other_categories_sk", defaults={"_locale":""})
  7074.      * @Route("/{_locale<%supported_locales%>?}/dalsie-kategorie",  name="product_other_categories_sk_locale", defaults={"_locale":""})
  7075.      * @Route("/dalsi-kategorie",                                   name="product_other_categories_cz", defaults={"_locale":""})
  7076.      * @Route("/{_locale<%supported_locales%>?}/dalsi-kategorie",   name="product_other_categories_cz_locale", defaults={"_locale":""})
  7077.      * @Route("/other-categories",                                  name="product_other_categories_en", defaults={"_locale":""})
  7078.      * @Route("/{_locale<%supported_locales%>?}/other-categories",  name="product_other_categories_en_locale", defaults={"_locale":""})
  7079.      * @param Request $request
  7080.      * @return Response
  7081.      * @throws \Exception
  7082.      */
  7083.     public function otherCategoriesAction(Request $request): Response
  7084.     {
  7085.         $data = [];
  7086.         $translator = $this->getTranslator();
  7087.         $multiStore = $this->getMultiStoreHelper($request);
  7088.         $domain = $multiStore->getDomain();
  7089.         $cache = $this->cache;
  7090.         $cacheKey = 'other.categories.page.v1.' . $domain->getId() . '.' . $request->getLocale();
  7091.         $cacheItem = $cache->getItem($cacheKey);
  7092.         if ($request->get('_route') == 'product_other_categories_sk' && $domain->getLanguage()->getCode() == 'cz') {
  7093.             return $this->redirectToRoute('product_other_categories_cz', [], 301);
  7094.         } elseif ($request->get('_route') == 'product_other_categories_cz' && $domain->getLanguage()->getCode() == 'sk') {
  7095.             return $this->redirectToRoute('product_other_categories_sk', [], 301);
  7096.         } elseif ($request->get('_route') == 'product_other_categories_sk_locale' && $domain->getLanguage()->getCode() == 'cz') {
  7097.             return $this->redirectToRoute('product_other_categories_cz_locale');
  7098.         } elseif ($request->get('_route') == 'product_other_categories_cz_locale' && $domain->getLanguage()->getCode() == 'sk') {
  7099.             return $this->redirectToRoute('product_other_categories_sk_locale');
  7100.         }
  7101.         if ($cacheItem->isHit()) {
  7102.             $data['sections'] = $cacheItem->get();
  7103.         } else {
  7104.             $entityManager = $this->getEntityManager();
  7105.             $productRepo = $entityManager->getRepository(Product::class);
  7106.             $seoUrlHelper = $this->getSeoUrlHelper($request);
  7107.             $productHelper = $this->getProductHelper($request);
  7108.             $data['sections'] = $productRepo->getOtherProductsSection($domain, $seoUrlHelper, $productHelper, $multiStore);
  7109.             $cacheItem->set($data['sections']);
  7110.             $cacheItem->expiresAfter(self::CACHE_LIFETIME_4_HOUR);
  7111.             $cache->save($cacheItem);
  7112.         }
  7113.         if (!empty($data['sections'])) {
  7114.             $data['seoTitle'] = $translator->trans('Other categories title');
  7115.             $data['seoDescription'] = $translator->trans('Other categories description');
  7116.             $data['canonical_link'] = '';
  7117.             $data['breadcrumbs'] = [
  7118.                 $this->getBreadCrumbsBase($request),
  7119.                 [
  7120.                     'text' => $translator->trans('Other categories title'),
  7121.                     'href' => '',
  7122.                 ],
  7123.             ];
  7124.             $data['partnerLoginRedirect'] = false;
  7125.             if (!is_null($request->query->get('partner-link')) && $request->query->get('partner-link') == 1 && !$this->getLoginHelper($request)->isLoggedIn()) {
  7126.                 $data['partnerLoginRedirectRoute'] = $this->generateUrl('partner_login');
  7127.                 $data['partnerLoginRedirect'] = true;
  7128.             }
  7129.             $data['header'] = $this->getHeader($request);
  7130.             $data['footer'] = $this->getFooter($request);
  7131.             return $this->render('AtechNetCoreBundle/Product/parts.html.twig', $data);
  7132.         }
  7133.         return $this->forward('App\AtechNet\CoreBundle\Controller\DefaultController::notFoundAction');
  7134.     }
  7135.     /**
  7136.      * @Route("/zsakbamacska", name="product_zsakbamacska_hu", defaults={"_locale":""})
  7137.      * @Route("/{_locale<%supported_locales%>?}/zsakbamacska", name="product_zsakbamacska_hu_locale", defaults={"_locale":""})
  7138.      * @param Request $request
  7139.      * @return Response
  7140.      * @throws \Exception
  7141.      */
  7142.     public function zsakbamacskaAction(Request $request): Response
  7143.     {
  7144.         $multiStore = $this->getMultiStoreHelper($request);
  7145.         $productHelper = $this->getProductHelper($request);
  7146.         $domain = $multiStore->getDomain();
  7147.         $domainId = $domain->getId();
  7148.         // Default Locale
  7149.         $defaultLocale = $multiStore->getDefaultLocale();
  7150.         $data = [];
  7151.         $data['warrantyYear'] = $this->getWarrantyForNonProductText($domainId);
  7152.         $data['priceWarrantyDay'] = $this->getWarrantyForNonProductText($domainId, 'priceWarrantyDay');
  7153.         $translator = $this->getTranslator();
  7154.         $data['seoTitle'] = $translator->trans('Parts SEO title');
  7155.         $data['seoDescription'] = $translator->trans('Furbicat description');
  7156.         $data['canonical_link'] = '';
  7157.         $data['breadcrumbs'] = [
  7158.             $this->getBreadCrumbsBase($request),
  7159.             [
  7160.                 'text' => $translator->trans('Furbify zsakbamacska title'),
  7161.                 'href' => '',
  7162.             ],
  7163.         ];
  7164.         $data['services_link'] = $this->url($request)->link('page', [
  7165.             'static_id' => $this->getServicesPageLink($defaultLocale),
  7166.         ]);
  7167.         $data['free_ship_limit'] = $productHelper::getFreeShipLimits()[$domainId]['freeShipLimit'];
  7168.         $deliveryDate = (new DeliveryDate())->getEstimatedDeliveryDate($domainId, false, false);
  7169.         $day = $deliveryDate->format('d.m.Y') . ', ' . $this->getTranslator()->trans($deliveryDate->format('l'));
  7170.         $data['estimated_deliver_date'] = $this->getTranslator()->trans('Estimated deliver is {day}', [
  7171.             'day' => $day,
  7172.         ]);
  7173.         $data['heading_title'] = $data['h1_title'] = $translator->trans('Furbify zsakbamacska title');
  7174.         $data['webshop_phone_number'] = $this->getContactInfos()['phone.webshop.' . $domain->getLanguage()->getCode() . '.' . $domain->getType()];
  7175.         $data['header'] = $this->getHeader($request);
  7176.         $data['footer'] = $this->getFooter($request);
  7177.         return $this->render('AtechNetCoreBundle/Product/zsakbamacska.html.twig', $data);
  7178.     }
  7179.     /**
  7180.      * @Route("/komponenty",                                    name="product_parts_sk", defaults={"_locale":""})
  7181.      * @Route("/{_locale<%supported_locales%>?}/komponenty",    name="product_parts_sk_locale", defaults={"_locale":""})
  7182.      * @Route("/alkatreszek",                                   name="product_parts_hu", defaults={"_locale":""})
  7183.      * @Route("/{_locale<%supported_locales%>?}/alkatreszek",   name="product_parts_hu_locale", defaults={"_locale":""})
  7184.      * @Route("/komponenty",                                    name="product_parts_cz", defaults={"_locale":""})
  7185.      * @Route("/{_locale<%supported_locales%>?}/komponenty",    name="product_parts_cz_locale", defaults={"_locale":""})
  7186.      * @Route("/components",                                    name="product_parts_en", defaults={"_locale":""})
  7187.      * @Route("/{_locale<%supported_locales%>?}/components",    name="product_parts_en_locale", defaults={"_locale":""})
  7188.      * @param Request $request
  7189.      * @return Response
  7190.      * @throws \Exception
  7191.      */
  7192.     public function partsAction(Request $request): Response
  7193.     {
  7194.         $data = [];
  7195.         $translator = $this->getTranslator();
  7196.         $multiStore = $this->getMultiStoreHelper($request);
  7197.         $domain = $multiStore->getDomain();
  7198.         $cache = $this->cache;
  7199.         $cacheKey = 'parts.page.v2.' . $domain->getId() . '.' . $request->getLocale();
  7200.         $cacheItem = $cache->getItem($cacheKey);
  7201.         if ($cacheItem->isHit()) {
  7202.             $data['sections'] = $cacheItem->get();
  7203.         } else {
  7204.             $entityManager = $this->getEntityManager();
  7205.             $productRepo = $entityManager->getRepository(Product::class);
  7206.             $seoUrlHelper = $this->getSeoUrlHelper($request);
  7207.             $productHelper = $this->getProductHelper($request);
  7208.             $data['sections'] = $productRepo->getPartsSections($domain, $seoUrlHelper, $productHelper, $multiStore);
  7209.             $cacheItem->set($data['sections']);
  7210.             $cacheItem->expiresAfter(self::CACHE_LIFETIME_4_HOUR);
  7211.             $cache->save($cacheItem);
  7212.         }
  7213.         if (!empty($data['sections'])) {
  7214.             $data['seoTitle'] = $translator->trans('Parts SEO title');
  7215.             $data['seoDescription'] = $translator->trans('Parts SEO description');
  7216.             $data['canonical_link'] = '';
  7217.             $data['breadcrumbs'] = [
  7218.                 $this->getBreadCrumbsBase($request),
  7219.                 [
  7220.                     'text' => $translator->trans('Parts title'),
  7221.                     'href' => '',
  7222.                 ],
  7223.             ];
  7224.             $data['partnerLoginRedirect'] = false;
  7225.             if (!is_null($request->query->get('partner-link')) && $request->query->get('partner-link') == 1 && !$this->getLoginHelper($request)->isLoggedIn()) {
  7226.                 $data['partnerLoginRedirectRoute'] = $this->generateUrl('partner_login');
  7227.                 $data['partnerLoginRedirect'] = true;
  7228.             }
  7229.             $data['header'] = $this->getHeader($request);
  7230.             $data['footer'] = $this->getFooter($request);
  7231.             return $this->render('AtechNetCoreBundle/Product/parts.html.twig', $data);
  7232.         }
  7233.         return $this->forward('App\AtechNet\CoreBundle\Controller\DefaultController::notFoundAction');
  7234.     }
  7235.     /**
  7236.      * @Route("/product/price-monitor/add", name="product_price_monitor", defaults={"_locale":""})
  7237.      * @Route("/{_locale<%supported_locales%>?}/product/price-monitor/add", name="product_price_monitor_locale", defaults={"_locale":""})
  7238.      * @param Request $request
  7239.      * @return JsonResponse
  7240.      * @throws \Exception
  7241.      */
  7242.     public function addProductPriceMonitorAction(Request $request): JsonResponse
  7243.     {
  7244.         $json = [];
  7245.         $translator = $this->getTranslator();
  7246.         $email = $request->request->get('email');
  7247.         if (empty($email)) {
  7248.             $json['error'] = $translator->trans('E-Mail address required');
  7249.         } elseif (!filter_var($email, FILTER_VALIDATE_EMAIL) || !checkdnsrr(substr($email, strpos($email, "@") + 1))) {
  7250.             $json['error'] = $translator->trans('E-Mail address does not appear to be valid');
  7251.         }
  7252.         if (empty($request->request->get('name'))) {
  7253.             $json['error'] = $translator->trans('Name required');
  7254.         }
  7255.         if (empty($request->request->get('price'))) {
  7256.             $json['error'] = $translator->trans('Price required');
  7257.         } else {
  7258.             $price = preg_replace("/[^0-9.]/", '', $request->request->get('price'));
  7259.             if ((float)$price <= 0) {
  7260.                 $json['error'] = $translator->trans('Invalid price');
  7261.             }
  7262.         }
  7263.         if (empty($request->request->get('sourcePrice'))) {
  7264.             $json['error'] = $translator->trans('Source price required');
  7265.         }
  7266.         if (empty($request->request->get('productId'))) {
  7267.             $json['error'] = $translator->trans('Product not found');
  7268.         }
  7269.         $entityManager = $this->getEntityManager();
  7270.         if (empty($json)) {
  7271.             // Product
  7272.             $product = $entityManager->getRepository(Product::class)->findOneById($request->request->get('productId'));
  7273.             if ($product) {
  7274.                 $multiStore = $this->getMultiStoreHelper($request);
  7275.                 // Price Check
  7276.                 $priceMeta = $product->getDomainMeta($multiStore->getDomain());
  7277.                 $productPrice = $priceMeta->getDomainVatPrice();
  7278.                 $productSpecialPrice = 0;
  7279.                 if ($priceMeta->isDiscounted()) {
  7280.                     $productSpecialPrice = $priceMeta->getDomainVatDiscount();
  7281.                 }
  7282.                 if (($productSpecialPrice > 0 && (float)$price > $productSpecialPrice) || ($productSpecialPrice == 0 && (float)$price > $productPrice)) {
  7283.                     $json['error'] = $translator->trans('Price must be lower than current price');
  7284.                 } else {
  7285.                     // Notification Details
  7286.                     $customerNotification = new CustomerNotification();
  7287.                     // Domain
  7288.                     $domain = $multiStore->getDomain();
  7289.                     $customerNotification->setDomain($domain);
  7290.                     // Product
  7291.                     $customerNotification->setProduct($product);
  7292.                     // Customer
  7293.                     $loggedInCustomerId = $request->getSession()->get('customerId');
  7294.                     if (is_numeric($loggedInCustomerId)) {
  7295.                         $customer = $entityManager->getRepository(Customer::class)->findOneById($loggedInCustomerId);
  7296.                         if ($customer) {
  7297.                             $customerNotification->setCustomer($customer);
  7298.                         }
  7299.                     }
  7300.                     // Visitor
  7301.                     $identifier = null;
  7302.                     if (is_null($customerNotification->getCustomer())) {
  7303.                         $identifier = hash('sha512', $request->getClientIp() . $request->server->get('HTTP_USER_AGENT'), false);
  7304.                         $customerNotification->setVisitor($identifier);
  7305.                     }
  7306.                     // Type
  7307.                     $customerNotification->setType(CustomerNotification::TYPE_PRICE_MONITOR);
  7308.                     // E-mail
  7309.                     $customerNotification->setEmail($request->request->get('email'));
  7310.                     // Name
  7311.                     $customerNotification->setName($request->request->get('name'));
  7312.                     // Price
  7313.                     $customerNotification->setPrice((float)$request->request->get('price'));
  7314.                     // SourcePrice
  7315.                     $customerNotification->setSourcePrice((float)$request->request->get('sourcePrice'));
  7316.                     // Unsubscribe Key
  7317.                     $customerNotification->setUnsubscribeKey(bin2hex(random_bytes(16)));
  7318.                     // Check duplicity
  7319.                     $queryBuilder = $entityManager->createQueryBuilder();
  7320.                     $queryBuilder
  7321.                         ->select('cn')
  7322.                         ->from('AtechNetCoreBundle:CustomerNotification', 'cn')
  7323.                         ->where('cn.product = :product')->setParameter(':product', $product)
  7324.                         ->andWhere('cn.domain = :domain')->setParameter(':domain', $domain);
  7325.                     $queryBuilder
  7326.                         ->andWhere(
  7327.                             $queryBuilder->expr()->orX(
  7328.                                 $queryBuilder->expr()->eq('cn.customer', ':customer'),
  7329.                                 $queryBuilder->expr()->eq('cn.email', ':email')
  7330.                             )
  7331.                         )
  7332.                         ->setParameter(':customer', $customerNotification->getCustomer())
  7333.                         ->setParameter(':email', $customerNotification->getEmail());
  7334.                     if (!is_null($identifier)) {
  7335.                         $queryBuilder
  7336.                             ->andWhere(
  7337.                                 $queryBuilder->expr()->orX(
  7338.                                     $queryBuilder->expr()->eq('cn.visitor', ':visitor')
  7339.                                 )
  7340.                             )
  7341.                             ->setParameter(':visitor', $identifier);
  7342.                     }
  7343.                     $query = $queryBuilder->setMaxResults(1)->getQuery();
  7344.                     $exists = $query->getResult();
  7345.                     if (empty($exists)) {
  7346.                         $entityManager->persist($customerNotification);
  7347.                         $entityManager->flush();
  7348.                         if (!is_null($customerNotification->getCustomer()) && $customerNotification->getCustomer()->getDomain()->getId() == Domain::DOMAIN_ID_WS_HU) {
  7349.                             $notificationEmailAddress = '';
  7350.                             if ($this->getEnvironment() == 'prod') {
  7351.                                 switch ($multiStore->getCustomerTypeId()) {
  7352.                                     case MultiStore::CUSTOMER_TYPE_RETAIL:
  7353.                                         $notificationEmailAddress = 'webshop@furbify.eu';
  7354.                                         break;
  7355.                                     case MultiStore::CUSTOMER_TYPE_WHOLESALE:
  7356.                                         $notificationEmailAddress = $customerNotification->getCustomer()->getSalesManager()->getEmail();
  7357.                                         break;
  7358.                                 }
  7359.                             } else {
  7360.                                 $notificationEmailAddress = 'YOUR_TEST_EMAIL_ADDRESS';
  7361.                             }
  7362.                             if ($notificationEmailAddress != '') {
  7363.                                 $mailer = $this->getMailer();
  7364.                                 $email = (new TemplatedEmail())
  7365.                                     ->subject('New price monitor setting: ' . $customerNotification->getName() . ' - ' . $product->getName())
  7366.                                     ->to($notificationEmailAddress)
  7367.                                     ->htmlTemplate('AtechNetCoreBundle/Email/priceMonitorCustomerServiceNotification.html.twig')
  7368.                                     ->context([
  7369.                                         'customerName' => $customerNotification->getName(),
  7370.                                         'productCode' => $product->getCode(),
  7371.                                         'productTitle' => $product->getName(),
  7372.                                         'wantedPrice' => $customerNotification->getPrice(),
  7373.                                         'currentPrice' => $customerNotification->getSourcePrice(),
  7374.                                         'currency' => $domain->getCurrency(),
  7375.                                     ]);
  7376.                                 $mailer->send($email);
  7377.                             }
  7378.                         }
  7379.                         $json['success'] = true;
  7380.                     } else {
  7381.                         $json['error'] = $translator->trans('You have already set up price monitoring for this product');
  7382.                     }
  7383.                 }
  7384.             } else {
  7385.                 $json['error'] = $translator->trans('Product not found');
  7386.             }
  7387.         }
  7388.         return new JsonResponse($json);
  7389.     }
  7390.     /**
  7391.      * @Route("/product/price-monitor/unsubscribe", name="product_price_monitor_remove", defaults={"_locale":""})
  7392.      * @param Request $request
  7393.      * @return RedirectResponse
  7394.      */
  7395.     public function removeProductPriceMonitorAction(Request $request): RedirectResponse
  7396.     {
  7397.         $entityManager = $this->getEntityManager();
  7398.         $multiStore = $this->getMultiStoreHelper($request);
  7399.         $productId = $request->query->get('p');
  7400.         $email = base64_decode($request->query->get('u'));
  7401.         $unsubscribeKey = base64_decode($request->query->get('k'));
  7402.         $domain = $multiStore->getDomain();
  7403.         $customerNotifications = $entityManager->createQuery("SELECT cn FROM AtechNetCoreBundle:CustomerNotification cn WHERE cn.domain = :domain AND cn.product = :product AND cn.email = :email")
  7404.             ->setParameters([
  7405.                 'domain' => $domain,
  7406.                 'product' => $productId,
  7407.                 'email' => $email,
  7408.             ])
  7409.             ->getResult();
  7410.         if ($customerNotifications) {
  7411.             /** @var CustomerNotification $customerNotification */
  7412.             foreach ($customerNotifications as $customerNotification) {
  7413.                 if (password_verify($email . 'fu' . $customerNotification->getUnsubscribeKey() . 'fy', $unsubscribeKey)) {
  7414.                     // Redirect Url
  7415.                     $seoUrl = $this->url($request);
  7416.                     $redirect = $seoUrl->link('product', [
  7417.                         'product_id' => $customerNotification->getProduct()->getId(),
  7418.                         'isBazaar'   => $customerNotification->getProduct()->isBazaar()
  7419.                     ]);
  7420.                     // Remove
  7421.                     $entityManager->remove($customerNotification);
  7422.                     $entityManager->flush();
  7423.                     return $this->redirect($redirect, 301);
  7424.                 }
  7425.             }
  7426.         }
  7427.         return $this->redirectToRoute('not_found');
  7428.     }
  7429.     /**
  7430.      * @Route("/product/stock-monitor/add", name="product_stock_monitor")
  7431.      * @param Request $request
  7432.      * @return JsonResponse
  7433.      * @throws \Exception
  7434.      */
  7435.     public function addProductStockMonitorAction(Request $request): JsonResponse
  7436.     {
  7437.         $json = [];
  7438.         $translator = $this->getTranslator();
  7439.         $email = $request->request->get('email');
  7440.         if (empty($email)) {
  7441.             $json['error'] = $translator->trans('E-Mail address required');
  7442.         } elseif (!filter_var($email, FILTER_VALIDATE_EMAIL) || !checkdnsrr(substr($email, strpos($email, "@") + 1))) {
  7443.             $json['error'] = $translator->trans('E-Mail address does not appear to be valid');
  7444.         }
  7445.         if (empty($request->request->get('name'))) {
  7446.             $json['error'] = $translator->trans('Name required');
  7447.         }
  7448.         if (empty($request->request->get('productId'))) {
  7449.             $json['error'] = $translator->trans('Product not found');
  7450.         }
  7451.         if (!empty($json)) {
  7452.             return new JsonResponse($json);
  7453.         }
  7454.         $entityManager = $this->getEntityManager();
  7455.         // Product
  7456.         $product = $entityManager->getRepository(Product::class)->findOneById($request->request->get('productId'));
  7457.         if (!$product) {
  7458.             $json['error'] = $translator->trans('Product not found');
  7459.             return new JsonResponse($json);
  7460.         }
  7461.         // Notification Details
  7462.         $customerNotification = new CustomerNotification();
  7463.         $multiStore = $this->getMultiStoreHelper($request);
  7464.         // Domain
  7465.         $domain = $multiStore->getDomain();
  7466.         $customerNotification->setDomain($domain);
  7467.         // Product
  7468.         $customerNotification->setProduct($product);
  7469.         // Customer
  7470.         $loggedInCustomerId = $request->getSession()->get('customerId');
  7471.         if (is_numeric($loggedInCustomerId)) {
  7472.             $customer = $entityManager->getRepository(Customer::class)->findOneById($loggedInCustomerId);
  7473.             if ($customer) {
  7474.                 $customerNotification->setCustomer($customer);
  7475.             }
  7476.         }
  7477.         // Visitor
  7478.         $identifier = null;
  7479.         if (is_null($customerNotification->getCustomer())) {
  7480.             $identifier = hash('sha512', $request->getClientIp() . $request->server->get('HTTP_USER_AGENT'), false);
  7481.             $customerNotification->setVisitor($identifier);
  7482.         }
  7483.         // Type
  7484.         $customerNotification->setType(CustomerNotification::TYPE_STOCK_MONITOR);
  7485.         // E-mail
  7486.         $customerNotification->setEmail($request->request->get('email'));
  7487.         // Name
  7488.         $customerNotification->setName($request->request->get('name'));
  7489.         // Unsubscribe Key
  7490.         $customerNotification->setUnsubscribeKey(bin2hex(random_bytes(16)));
  7491.         // Check duplicity
  7492.         $queryBuilder = $entityManager->createQueryBuilder();
  7493.         $queryBuilder
  7494.             ->select('cn')
  7495.             ->from('AtechNetCoreBundle:CustomerNotification', 'cn')
  7496.             ->where('cn.product = :product')->setParameter(':product', $product)
  7497.             ->andWhere('cn.domain = :domain')->setParameter(':domain', $domain);
  7498.         $queryBuilder
  7499.             ->andWhere(
  7500.                 $queryBuilder->expr()->orX(
  7501.                     $queryBuilder->expr()->eq('cn.customer', ':customer'),
  7502.                     $queryBuilder->expr()->eq('cn.email', ':email')
  7503.                 )
  7504.             )
  7505.             ->setParameter(':customer', $customerNotification->getCustomer())
  7506.             ->setParameter(':email', $customerNotification->getEmail());
  7507.         if (!is_null($identifier)) {
  7508.             $queryBuilder
  7509.                 ->andWhere(
  7510.                     $queryBuilder->expr()->orX(
  7511.                         $queryBuilder->expr()->eq('cn.visitor', ':visitor')
  7512.                     )
  7513.                 )
  7514.                 ->setParameter(':visitor', $identifier);
  7515.         }
  7516.         $query = $queryBuilder->setMaxResults(1)->getQuery();
  7517.         $exists = $query->getResult();
  7518.         if (!empty($exists)) {
  7519.             $json['error'] = $translator->trans('You have already set up stock monitoring for this product');
  7520.             return new JsonResponse($json);
  7521.         }
  7522.         $entityManager->persist($customerNotification);
  7523.         $entityManager->flush();
  7524.         if (!is_null($customerNotification->getCustomer()) && $customerNotification->getCustomer()->getDomain()->getId() == Domain::DOMAIN_ID_WS_HU) {
  7525.             $notificationEmailAddress = '';
  7526.             if ($this->getEnvironment() == 'prod') {
  7527.                 switch ($multiStore->getCustomerTypeId()) {
  7528.                     case MultiStore::CUSTOMER_TYPE_RETAIL:
  7529.                         $notificationEmailAddress = 'webshop@furbify.eu';
  7530.                         break;
  7531.                     case MultiStore::CUSTOMER_TYPE_WHOLESALE:
  7532.                         $notificationEmailAddress = $customerNotification->getCustomer()->getSalesManager()->getEmail();
  7533.                         break;
  7534.                 }
  7535.             } else {
  7536.                 $notificationEmailAddress = 'lakasand@gmail.com';
  7537.             }
  7538.             if ($notificationEmailAddress != '') {
  7539.                 $mailer = $this->getMailer();
  7540.                 $email = (new TemplatedEmail())
  7541.                     ->subject("New price monitor setting: {$customerNotification->getName()} - {$product->getName()}")
  7542.                     ->to($notificationEmailAddress)
  7543.                     ->htmlTemplate('AtechNetCoreBundle/Email/priceMonitorCustomerServiceNotification.html.twig')
  7544.                     ->context([
  7545.                         'customerName' => $customerNotification->getName(),
  7546.                         'productCode' => $product->getCode(),
  7547.                         'productTitle' => $product->getName(),
  7548.                         'wantedPrice' => $customerNotification->getPrice(),
  7549.                         'currentPrice' => $customerNotification->getSourcePrice(),
  7550.                         'currency' => $domain->getCurrency(),
  7551.                     ]);
  7552.                 $mailer->send($email);
  7553.             }
  7554.         }
  7555.         $json['success'] = true;
  7556.         return new JsonResponse($json);
  7557.     }
  7558.     /**
  7559.      * @Route("/product/get/admin-login-panel-data", name="product_admin_login_data_ajax", defaults={"_locale":""})
  7560.      * @Route("/{_locale<%supported_locales%>?}/product/get/admin-login-panel-data", name="product_admin_login_data_ajax_locale", defaults={"_locale":""})
  7561.      * @param Request $request
  7562.      * @return JsonResponse
  7563.      */
  7564.     public function getDataForAdminLoginPanelAjaxAction(Request $request): JsonResponse
  7565.     {
  7566.         $productId = $request->get('productId') ?? false;
  7567.         $entityManager = $this->getEntityManager();
  7568.         $productRepo = $entityManager->getRepository(Product::class);
  7569.         $product = $productRepo->findOneById($productId);
  7570.         $data = [
  7571.             'avaragePurchasePrie' => $product->getAvgPrice(),
  7572.             'lastPurchasePrice' => $product->getLastPrice(),
  7573.             'inStock' => $product->getInStock(),
  7574.             'available' => $product->getAvailable(),
  7575.         ];
  7576.         return new JsonResponse($data);
  7577.     }
  7578.     /**
  7579.      * @Route("/product/get/stock-item-albums", name="product_stock_item_albums_ajax", defaults={"_locale":""})
  7580.      * @Route("/{_locale<%supported_locales%>?}/product/get/stock-item-albums", name="product_stock_item_albums_ajax_locale", defaults={"_locale":""})
  7581.      * @param Request $request
  7582.      * @return JsonResponse
  7583.      */
  7584.     public function getStockItemAlbumsAjaxAction(Request $request): JsonResponse
  7585.     {
  7586.         $productId = $request->get('productId') ?? false;
  7587.         $entityManager = $this->getEntityManager();
  7588.         $product = $entityManager->getRepository(Product::class)->findOneById($productId);
  7589.         $albums = $entityManager->getRepository(Product::class)->getStockItemAlbums(
  7590.             $productId,
  7591.             $product->isContainer(),
  7592.         );
  7593.         $selectedStockItems = $request->getSession()->get('stockItemCodes')[$productId] ?? false;
  7594.         if ($selectedStockItems) {
  7595.             foreach ($selectedStockItems as $stockItemCode) {
  7596.                 foreach ($albums as $key => $album) {
  7597.                     if ($album['aikenCode'] == $stockItemCode) {
  7598.                         $albums[$key]['selected'] = true;
  7599.                     }
  7600.                 }
  7601.             }
  7602.         }
  7603.         return new JsonResponse($albums);
  7604.     }
  7605.     /**
  7606.      * @Route("/product/get/album-images", name="product_album_images_ajax", defaults={"_locale":""})
  7607.      * @Route("/{_locale<%supported_locales%>?}/product/get/album-images", name="product_album_images_ajax_locale", defaults={"_locale":""})
  7608.      * @param Request $request
  7609.      * @return JsonResponse
  7610.      * @throws \Exception
  7611.      */
  7612.     public function getAlbumImagesAjaxAction(Request $request): JsonResponse
  7613.     {
  7614.         $albumId = $request->get('albumId') ?? false;
  7615.         $productHelper = $this->getProductHelper($request);
  7616.         $images = $productHelper->getAlbumImages($albumId);
  7617.         return new JsonResponse($images);
  7618.     }
  7619.     /**
  7620.      * @Route("/product/get/error-codes", name="product_error_codes_ajax", defaults={"_locale":""})
  7621.      * @Route("/{_locale<%supported_locales%>?}/product/get/error-codes", name="product_error_codes_ajax_locale", defaults={"_locale":""})
  7622.      */
  7623.     public function getErrorCodesForStockItemAjaxAction(Request $request): JsonResponse
  7624.     {
  7625.         $aikenCode = $request->get('aikenCode') ?? false;
  7626.         $languageCode = $this->getMultiStoreHelper($request)->getDomain()->getLanguage()->getCode();
  7627.         $si = $this->getEntityManager()->getRepository(StockItem::class)->findOneBy(['aikenCode' => $aikenCode]);
  7628.         $errors = $this->getEntityManager()->getRepository(Product::class)->getVisibleErrorCodes($si);
  7629.         return new JsonResponse(
  7630.             array_map(fn(ErrorCode $ec) => $ec->getTextForLanguage($languageCode), $errors)
  7631.         );
  7632.     }
  7633.     /**
  7634.      * @Route("/porovnanie", name="product_compare_sk")
  7635.      * @Route("/osszehasonlitas", name="product_compare_hu")
  7636.      * @Route("/porovnani", name="product_compare_cz")
  7637.      * @Route("/compare", name="product_compare_en")
  7638.      * @param Request $request
  7639.      * @return Response
  7640.      */
  7641.     public function compareAction(Request $request): Response
  7642.     {
  7643.         $data = [];
  7644.         // Entity Manager
  7645.         $entityManager = $this->getEntityManager();
  7646.         // Multi-store
  7647.         $multiStore = $this->getMultiStoreHelper($request);
  7648.         // Translator (database)
  7649.         $databaseTranslator = $this->getDatabaseTranslator($request);
  7650.         // Translator
  7651.         $translator = $this->getTranslator();
  7652.         // Session
  7653.         $session = $request->getSession();
  7654.         // Domain
  7655.         $domain = $multiStore->getDomain();
  7656.         // Collection
  7657.         if ($session->has('productCompare')) {
  7658.             $collection = $session->get('productCompare');
  7659.         } else {
  7660.             $collection = [];
  7661.         }
  7662.         // Reverse Order
  7663.         $collection = array_reverse($collection);
  7664.         // Placeholder
  7665.         $placeholder = $image = $this->getImage('placeholder.jpg', '')->resize(Image::PRODUCT_VIEW_ADDITIONAL_WIDTH, Image::PRODUCT_VIEW_ADDITIONAL_HEIGHT);
  7666.         // Specification Attributes
  7667.         $specificationAttributes = [];
  7668.         // Products
  7669.         $products = [];
  7670.         foreach ($collection as $productId) {
  7671.             /** @var Product $product */
  7672.             $product = $entityManager->getRepository(Product::class)->findOneById($productId);
  7673.             if ($product) {
  7674.                 // Meta
  7675.                 $priceMeta = $product->getDomainMeta($domain);
  7676.                 // Product Image
  7677.                 if ($product->getAlbum() && $product->getAlbum()->getPhotos()->count() > 0) {
  7678.                     $image = $this->getImage($product->getAlbum()->getPhotos()->first(), 'product/' . $product->getCode())->resize(Image::PRODUCT_VIEW_ADDITIONAL_WIDTH, Image::PRODUCT_VIEW_ADDITIONAL_HEIGHT);
  7679.                 } else {
  7680.                     $image = $placeholder;
  7681.                 }
  7682.                 // Product Price
  7683.                 if ($priceMeta->isDiscounted()) {
  7684.                     $price = $domain->getType() == Domain::TYPE_RETAIL ? $priceMeta->getDomainVatDiscount() : $priceMeta->getDomainDiscount();
  7685.                 } else {
  7686.                     $price = $domain->getType() == Domain::TYPE_RETAIL ? $priceMeta->getDomainVatPrice() : $priceMeta->getDomainPrice();
  7687.                 }
  7688.                 // WebCam Included
  7689.                 $isWebcamIncluded = false;
  7690.                 // Specification
  7691.                 $specification = [];
  7692.                 foreach ($product->getSpecificationProductAttributeOptions() as $spec) {
  7693.                     $option = $spec->getOption();
  7694.                     $attribute = $option->getAttribute();
  7695.                     $attributeId = $attribute->getId();
  7696.                     if ($attributeId == Attribute::ATTRIBUTE_ID_QUALITY || ($attributeId == Attribute::ATTRIBUTE_ID_OPERATING_SYSTEM && in_array($domain->getId(), [Domain::DOMAIN_ID_RT_EU, Domain::DOMAIN_ID_WS_EU]))) {
  7697.                         continue;
  7698.                     }
  7699.                     // Specification Attribute
  7700.                     if (!isset($specificationAttributes[$attributeId])) {
  7701.                         $specificationAttributes[$attributeId] = [
  7702.                             'id' => $attributeId,
  7703.                             'title' => $attribute->getTitle($databaseTranslator),
  7704.                             'sortIndex' => $attribute->getSortIndex(),
  7705.                         ];
  7706.                     }
  7707.                     // Specfication
  7708.                     if (!isset($specification[$attributeId])) {
  7709.                         $specification[$attributeId] = [];
  7710.                         if ($attributeId == Attribute::ATTRIBUTE_ID_WEBCAM) {
  7711.                             $isWebcamIncluded = true;
  7712.                         }
  7713.                     }
  7714.     
  7715.                     $title = $option->getLongTitle($databaseTranslator);
  7716.                     if (empty($title)) {
  7717.                         $title = $option->getTitle($databaseTranslator);
  7718.                     }
  7719.                     $specification[$attributeId][$spec->getId()] = [
  7720.                         'id' => $spec->getId(),
  7721.                         'attributeOptionId' => $option->getId(),
  7722.                         'title' => $title,
  7723.                         'shortTitle' => $option->getTitle($databaseTranslator),
  7724.                         'multiplier' => $spec->getMultiplier(),
  7725.                     ];
  7726.                 }
  7727.                 // WebCam
  7728.                 if (!$isWebcamIncluded && $product->getType()->getId() == ProductType::PRODUCT_TYPE_ID_NOTEBOOK) {
  7729.                     // Attribute
  7730.                     $attribute = $entityManager->getRepository(Attribute::class)->findOneById(Attribute::ATTRIBUTE_ID_WEBCAM);
  7731.                     if ($attribute) {
  7732.                         // Specification Attribute
  7733.                         if (!isset($specificationAttributes[Attribute::ATTRIBUTE_ID_WEBCAM])) {
  7734.                             $specificationAttributes[Attribute::ATTRIBUTE_ID_WEBCAM] = [
  7735.                                 'id' => Attribute::ATTRIBUTE_ID_WEBCAM,
  7736.                                 'title' => $attribute->getTitle($databaseTranslator),
  7737.                                 'sortIndex' => $attribute->getSortIndex(),
  7738.                             ];
  7739.                         }
  7740.                         // Specification
  7741.                         $specification[Attribute::ATTRIBUTE_ID_WEBCAM][1773] = [
  7742.                             'id' => 1773,
  7743.                             'title' => $translator->trans('No'),
  7744.                             'shortTitle' => $translator->trans('No'),
  7745.                             'multiplier' => 0,
  7746.                         ];
  7747.                     }
  7748.                 }
  7749.                 if ($priceMeta->isReady() && $priceMeta->isActive() && $product->isReservable()) {
  7750.                     $outOfStockStatus = $product->getOutOfStockStatus();
  7751.                     if ($outOfStockStatus == Product::OutOfStockStatus_VisibleOrderable5Days) {
  7752.                         $orderWaitingDays = 5;
  7753.                     } elseif ($outOfStockStatus == Product::OutOfStockStatus_VisibleOrderable10Days) {
  7754.                         $orderWaitingDays = 10;
  7755.                     } elseif ($outOfStockStatus == Product::OutOfStockStatus_VisibleOrderable15Days) {
  7756.                         $orderWaitingDays = 15;
  7757.                     } else {
  7758.                         $orderWaitingDays = 0;
  7759.                     }
  7760.                 } else {
  7761.                     $orderWaitingDays = 0;
  7762.                 }
  7763.                 // Weight
  7764.                 $weight = ($product->getWeight() != 0 ? number_format($product->getWeight() / 1000, 1, ',', ' ') . ' kg' : '');
  7765.                 // Dimensions
  7766.                 $dimensions = [];
  7767.                 if ($product->getWidth() != 0) {
  7768.                     $dimensions[] = $product->getWidth() . ' mm';
  7769.                 }
  7770.                 if ($product->getLength() != 0) {
  7771.                     $dimensions[] = $product->getLength() . ' mm';
  7772.                 }
  7773.                 if ($product->getHeight() != 0) {
  7774.                     $dimensions[] = $product->getHeight() . ' mm';
  7775.                 }
  7776.                 $dimensions = !empty($dimensions) ? implode(' x ', $dimensions) : '';
  7777.                 // Product Data
  7778.                 $products[] = [
  7779.                     'id' => $product->getId(),
  7780.                     'href' => $this->url($request)->link('product', [
  7781.                         'product_id' => $product->getId(),
  7782.                         'isBazaar'   => $product->isBazaar()
  7783.                     ]),
  7784.                     'name' => $product->getFullTitle($databaseTranslator),
  7785.                     'image' => $image,
  7786.                     'price' => $price,
  7787.                     'brand' => $product->getVendor()->getName(),
  7788.                     'model' => in_array($domain->getId(), [Domain::DOMAIN_ID_RT_EU, Domain::DOMAIN_ID_WS_EU]) ? str_replace([' (Quality: Bazar)', ' (Quality: Bazár)', ' (Quality: Bazár, '], ['', '', ' ('], $product->getName()) : $product->getName(),
  7789.                     'code' => $product->getCode(),
  7790.                     'available' => $product->getAvailable(),
  7791.                     'orderWaitingDays' => $orderWaitingDays,
  7792.                     'quality' => $product->getQualityStatusTitle($product->getQualityStatus()),
  7793.                     'specification' => $specification,
  7794.                     'dimensions' => $dimensions,
  7795.                     'weight' => $weight,
  7796.                 ];
  7797.             }
  7798.         }
  7799.         $data['products'] = $products;
  7800.         // Sort Order Specification Attributes
  7801.         $sortOrder = [];
  7802.         foreach ($specificationAttributes as $key => $value) {
  7803.             $sortOrder[$key] = (int)$value['sortIndex'];
  7804.         }
  7805.         array_multisort($sortOrder, SORT_ASC, SORT_NUMERIC, $specificationAttributes);
  7806.         $data['attributes'] = $specificationAttributes;
  7807.         // Currency
  7808.         $data['currency'] = $domain->getCurrency();
  7809.         $data['precision'] = $domain->getPricePrecision();
  7810.         // Common
  7811.         $data['header'] = $this->getHeader($request);
  7812.         $data['footer'] = $this->getFooter($request);
  7813.         $data['contentBottom'] = $this->getContentBottom($request);
  7814.         return $this->render('AtechNetCoreBundle/Product/compare.html.twig', $data);
  7815.     }
  7816.     /**
  7817.      * @Route("/compare/add", name="product_compare_add")
  7818.      * @param Request $request
  7819.      * @return JsonResponse
  7820.      */
  7821.     public function compareAddAction(Request $request): JsonResponse
  7822.     {
  7823.         $json = [];
  7824.         // Entity Manager
  7825.         $entityManager = $this->getEntityManager();
  7826.         // Multi-store
  7827.         $multiStore = $this->getMultiStoreHelper($request);
  7828.         // Translator
  7829.         $databaseTranslator = $this->getDatabaseTranslator($request);
  7830.         // Session
  7831.         $session = $request->getSession();
  7832.         // Domain
  7833.         $domain = $multiStore->getDomain();
  7834.         
  7835.         // Collection
  7836.         if ($session->has('productCompare')) {
  7837.             $collection = $session->get('productCompare');
  7838.         } else {
  7839.             $collection = [];
  7840.         }
  7841.         // Product Id
  7842.         if ($request->request->has('productId')) {
  7843.             $productId = $request->request->get('productId');
  7844.         } else {
  7845.             $productId = 0;
  7846.         }
  7847.         // Product Info
  7848.         $product = $entityManager->getRepository(Product::class)->findOneById($productId);
  7849.         if ($product) {
  7850.             // If already in array remove the product id so it will be added to the back of the array
  7851.             $key = array_search($productId, $collection);
  7852.             if ($key !== false) {
  7853.                 unset($collection[$key]);
  7854.             }
  7855.             // If we count a numeric value that is greater than 4 products, we remove the first one
  7856.             if (count($collection) >= 4) {
  7857.                 array_shift($collection);
  7858.             }
  7859.             // Check product types
  7860.             if (count($collection) > 0) {
  7861.                 /**
  7862.                  * @var Product $productInCollection
  7863.                  */
  7864.                 $productInCollection = $entityManager->getRepository(Product::class)->findOneById($collection[0]);
  7865.                 if ($productInCollection->getType()->getId() != $product->getType()->getId()) {
  7866.                     return new JsonResponse([
  7867.                         'message' => 'Different product type added',
  7868.                     ]);
  7869.                 }
  7870.             }
  7871.             // Push to Collection
  7872.             $collection[] = $productId;
  7873.             // Save to Session
  7874.             $session->set('productCompare', $collection);
  7875.             // Placeholder
  7876.             $placeholder = $image = $this->getImage('placeholder.jpg', '')->resize(Image::PRODUCT_VIEW_ADDITIONAL_WIDTH, Image::PRODUCT_VIEW_ADDITIONAL_HEIGHT);
  7877.             // Compared Products
  7878.             $json['product'] = [];
  7879.             foreach ($collection as $productId) {
  7880.                 $product = $entityManager->getRepository(Product::class)->findOneById($productId);
  7881.                 if ($product) {
  7882.                     // Meta
  7883.                     $priceMeta = $product->getDomainMeta($domain);
  7884.                     // Product Image
  7885.                     if ($product->getAlbum() && $product->getAlbum()->getPhotos()->count() > 0) {
  7886.                         $image = $this->getImage($product->getAlbum()->getPhotos()->first(), 'product/' . $product->getCode())->resize(Image::PRODUCT_VIEW_ADDITIONAL_WIDTH, Image::PRODUCT_VIEW_ADDITIONAL_HEIGHT);
  7887.                     } else {
  7888.                         $image = $placeholder;
  7889.                     }
  7890.                     // Product Price
  7891.                     if ($priceMeta->isDiscounted()) {
  7892.                         $price = $domain->getType() == Domain::TYPE_RETAIL ? $priceMeta->getDomainVatDiscount() : $priceMeta->getDomainDiscount();
  7893.                     } else {
  7894.                         $price = $domain->getType() == Domain::TYPE_RETAIL ? $priceMeta->getDomainVatPrice() : $priceMeta->getDomainPrice();
  7895.                     }
  7896.                     // Product Data
  7897.                     $json['product'][] = [
  7898.                         'id' => $product->getId(),
  7899.                         'name' => $product->getFullTitle($databaseTranslator),
  7900.                         'image' => $image,
  7901.                         'price' => $price,
  7902.                     ];
  7903.                 }
  7904.             }
  7905.         }
  7906.         return new JsonResponse($json);
  7907.     }
  7908.     /**
  7909.      * @Route("/compare/remove", name="product_compare_remove")
  7910.      * @param Request $request
  7911.      * @return JsonResponse
  7912.      */
  7913.     public function compareRemoveAction(Request $request): JsonResponse
  7914.     {
  7915.         $json = [];
  7916.         // Entity Manager
  7917.         $entityManager = $this->getEntityManager();
  7918.         // Multi-store
  7919.         $multiStore = $this->getMultiStoreHelper($request);
  7920.         // Translator
  7921.         $databaseTranslator = $this->getDatabaseTranslator($request);
  7922.         // Session
  7923.         $session = $request->getSession();
  7924.         // Domain
  7925.         $domain = $multiStore->getDomain();
  7926.         
  7927.         // Collection
  7928.         if ($session->has('productCompare')) {
  7929.             $collection = $session->get('productCompare');
  7930.         } else {
  7931.             $collection = [];
  7932.         }
  7933.         // Product Id
  7934.         if ($request->request->has('productId')) {
  7935.             $productId = $request->request->get('productId');
  7936.         } else {
  7937.             $productId = 0;
  7938.         }
  7939.         // Remove the product id
  7940.         $key = array_search($productId, $collection);
  7941.         if ($key !== false) {
  7942.             unset($collection[$key]);
  7943.         }
  7944.         // If we count a numeric value that is greater than 4 products, we remove the first one
  7945.         if (count($collection) > 4) {
  7946.             array_shift($collection);
  7947.         }
  7948.         // Save to Session
  7949.         $session->set('productCompare', $collection);
  7950.         // Placeholder
  7951.         $placeholder = $image = $this->getImage('placeholder.jpg', '')->resize(Image::PRODUCT_VIEW_ADDITIONAL_WIDTH, Image::PRODUCT_VIEW_ADDITIONAL_HEIGHT);
  7952.         // Compared Products
  7953.         $json['product'] = [];
  7954.         foreach ($collection as $productId) {
  7955.             $product = $entityManager->getRepository(Product::class)->findOneById($productId);
  7956.             if ($product) {
  7957.                 // Meta
  7958.                 $priceMeta = $product->getDomainMeta($domain);
  7959.                 // Product Image
  7960.                 if ($product->getAlbum() && $product->getAlbum()->getPhotos()->count() > 0) {
  7961.                     $image = $this->getImage($product->getAlbum()->getPhotos()->first(), 'product/' . $product->getCode())->resize(Image::PRODUCT_VIEW_ADDITIONAL_WIDTH, Image::PRODUCT_VIEW_ADDITIONAL_HEIGHT);
  7962.                 } else {
  7963.                     $image = $placeholder;
  7964.                 }
  7965.                 // Product Price
  7966.                 if ($priceMeta->isDiscounted()) {
  7967.                     $price = $domain->getType() == Domain::TYPE_RETAIL ? $priceMeta->getDomainVatDiscount() : $priceMeta->getDomainDiscount();
  7968.                 } else {
  7969.                     $price = $domain->getType() == Domain::TYPE_RETAIL ? $priceMeta->getDomainVatPrice() : $priceMeta->getDomainPrice();
  7970.                 }
  7971.                 // Product Data
  7972.                 $json['product'][] = [
  7973.                     'id' => $product->getId(),
  7974.                     'name' => $product->getFullTitle($databaseTranslator),
  7975.                     'image' => $image,
  7976.                     'price' => $price,
  7977.                 ];
  7978.             }
  7979.         }
  7980.         return new JsonResponse($json);
  7981.     }
  7982.     /**
  7983.      * @Route("/compare/fetch", name="product_compare_fetch")
  7984.      * @param Request $request
  7985.      * @return JsonResponse
  7986.      */
  7987.     public function compareFetchAction(Request $request): JsonResponse
  7988.     {
  7989.         $json = [];
  7990.         // Entity Manager
  7991.         $entityManager = $this->getEntityManager();
  7992.         // Multi-store
  7993.         $multiStore = $this->getMultiStoreHelper($request);
  7994.         // Translator
  7995.         $databaseTranslator = $this->getDatabaseTranslator($request);
  7996.         // Session
  7997.         $session = $request->getSession();
  7998.         // Domain
  7999.         $domain = $multiStore->getDomain();
  8000.         
  8001.         // Collection
  8002.         if ($session->has('productCompare')) {
  8003.             $collection = $session->get('productCompare');
  8004.         } else {
  8005.             $collection = [];
  8006.         }
  8007.         // If we count a numeric value that is greater than 4 products, we remove the first one
  8008.         if (count($collection) > 4) {
  8009.             array_shift($collection);
  8010.         }
  8011.         // Save to Session
  8012.         $session->set('productCompare', $collection);
  8013.         // Placeholder
  8014.         $placeholder = $image = $this->getImage('placeholder.jpg', '')->resize(Image::PRODUCT_VIEW_ADDITIONAL_WIDTH, Image::PRODUCT_VIEW_ADDITIONAL_HEIGHT);
  8015.         // Compared Products
  8016.         $json['product'] = [];
  8017.         foreach ($collection as $productId) {
  8018.             $product = $entityManager->getRepository(Product::class)->findOneById($productId);
  8019.             if ($product) {
  8020.                 // Meta
  8021.                 $priceMeta = $product->getDomainMeta($domain);
  8022.                 // Product Image
  8023.                 if ($product->getAlbum() && $product->getAlbum()->getPhotos()->count() > 0) {
  8024.                     $image = $this->getImage($product->getAlbum()->getPhotos()->first(), 'product/' . $product->getCode())->resize(Image::PRODUCT_VIEW_ADDITIONAL_WIDTH, Image::PRODUCT_VIEW_ADDITIONAL_HEIGHT);
  8025.                 } else {
  8026.                     $image = $placeholder;
  8027.                 }
  8028.                 // Product Price
  8029.                 if ($priceMeta->isDiscounted()) {
  8030.                     $price = $domain->getType() == Domain::TYPE_RETAIL ? $priceMeta->getDomainVatDiscount() : $priceMeta->getDomainDiscount();
  8031.                 } else {
  8032.                     $price = $domain->getType() == Domain::TYPE_RETAIL ? $priceMeta->getDomainVatPrice() : $priceMeta->getDomainPrice();
  8033.                 }
  8034.                 // Product Data
  8035.                 $json['product'][] = [
  8036.                     'id' => $product->getId(),
  8037.                     'name' => $product->getFullTitle($databaseTranslator),
  8038.                     'image' => $image,
  8039.                     'price' => $price,
  8040.                 ];
  8041.             }
  8042.         }
  8043.         return new JsonResponse($json);
  8044.     }
  8045.     /**
  8046.      * @param $value
  8047.      * @return string
  8048.      */
  8049.     private function removeSpecialCharacters($value): string
  8050.     {
  8051.         $table = [
  8052.             ' ' => '',
  8053.             'Š' => 'S',
  8054.             'š' => 's',
  8055.             'Ð' => 'Dj',
  8056.             'Ž' => 'Z',
  8057.             'ž' => 'z',
  8058.             'C' => 'C',
  8059.             'c' => 'c',
  8060.             'C' => 'C',
  8061.             'c' => 'c',
  8062.             'À' => 'A',
  8063.             'Á' => 'A',
  8064.             'Â' => 'A',
  8065.             'Ã' => 'A',
  8066.             'Ä' => 'A',
  8067.             'Å' => 'A',
  8068.             'Æ' => 'A',
  8069.             'Ç' => 'C',
  8070.             'È' => 'E',
  8071.             'É' => 'E',
  8072.             'Ê' => 'E',
  8073.             'Ë' => 'E',
  8074.             'Ì' => 'I',
  8075.             'Í' => 'I',
  8076.             'Î' => 'I',
  8077.             'Ï' => 'I',
  8078.             'Ñ' => 'N',
  8079.             'Ò' => 'O',
  8080.             'Ó' => 'O',
  8081.             'Ô' => 'O',
  8082.             'Õ' => 'O',
  8083.             'Ö' => 'O',
  8084.             'Ø' => 'O',
  8085.             'Ù' => 'U',
  8086.             'Ú' => 'U',
  8087.             'Û' => 'U',
  8088.             'Ü' => 'U',
  8089.             'Ý' => 'Y',
  8090.             'Þ' => 'B',
  8091.             'ß' => 'Ss',
  8092.             'à' => 'a',
  8093.             'á' => 'a',
  8094.             'â' => 'a',
  8095.             'ã' => 'a',
  8096.             'ä' => 'a',
  8097.             'å' => 'a',
  8098.             'æ' => 'a',
  8099.             'ç' => 'c',
  8100.             'è' => 'e',
  8101.             'é' => 'e',
  8102.             'ê' => 'e',
  8103.             'ë' => 'e',
  8104.             'ì' => 'i',
  8105.             'í' => 'i',
  8106.             'î' => 'i',
  8107.             'ï' => 'i',
  8108.             'ð' => 'o',
  8109.             'ñ' => 'n',
  8110.             'ò' => 'o',
  8111.             'ó' => 'o',
  8112.             'ô' => 'o',
  8113.             'õ' => 'o',
  8114.             'ö' => 'o',
  8115.             'ø' => 'o',
  8116.             'ù' => 'u',
  8117.             'ú' => 'u',
  8118.             'û' => 'u',
  8119.             'ý' => 'y',
  8120.             'ý' => 'y',
  8121.             'þ' => 'b',
  8122.             'ÿ' => 'y',
  8123.             'R' => 'R',
  8124.             'r' => 'r',
  8125.             "'" => '',
  8126.             '"' => '',
  8127.             '(' => '',
  8128.             ')' => '',
  8129.             ',' => '',
  8130.             '+' => '',
  8131.             '–' => '',
  8132.             '.' => '',
  8133.             '-' => '',
  8134.             '3' => 'Three',
  8135.             'ü' => 'u',
  8136.             'ű' => 'u',
  8137.             'Ü' => 'U',
  8138.             'Ű' => 'U',
  8139.             'ő' => 'o',
  8140.             'Ő' => 'O',
  8141.             'ő' => 'o',
  8142.         ];
  8143.         return strtr($value, $table);
  8144.     }
  8145. }