src/AtechNet/CoreBundle/Service/Furbify/BazaarService.php line 65

Open in your IDE?
  1. <?php
  2. namespace App\AtechNet\CoreBundle\Service\Furbify;
  3. use App\AtechNet\CoreBundle\Entity\Banner;
  4. use App\AtechNet\CoreBundle\Entity\BannerItem;
  5. use App\AtechNet\CoreBundle\Entity\CategoryGroup;
  6. use App\AtechNet\CoreBundle\Entity\Domain;
  7. use App\AtechNet\CoreBundle\Entity\Language;
  8. use App\AtechNet\CoreBundle\Entity\Product;
  9. use App\AtechNet\CoreBundle\Helper\Furbify\Image;
  10. use App\AtechNet\CoreBundle\Helper\Furbify\MultiStore;
  11. use App\AtechNet\CoreBundle\Helper\Furbify\ProductHelper;
  12. use App\AtechNet\CoreBundle\Helper\Furbify\SeoUrlHelper;
  13. use Doctrine\Common\Collections\ArrayCollection;
  14. use Doctrine\Common\Collections\Criteria;
  15. use Doctrine\ORM\EntityManagerInterface;
  16. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  17. use Symfony\Contracts\Cache\CacheInterface;
  18. use Symfony\Contracts\Cache\ItemInterface;
  19. use Symfony\Contracts\Translation\TranslatorInterface;
  20. use Psr\Cache\CacheItemPoolInterface;
  21. class BazaarService 
  22. {
  23.     /** @var MultiStore */
  24.     private MultiStore $multiStore;
  25.     /** @var ProductHelper */
  26.     private ProductHelper $productHelper;
  27.     /** @var SeoUrlHelper */
  28.     private SeoUrlHelper $seoUrlHelper;
  29.     public function __construct(
  30.         private ImageService $imageService, 
  31.         private ProductService $productService, 
  32.         private EntityManagerInterface $entityManager, 
  33.         // private TranslatorInterface $translator, 
  34.         private CacheItemPoolInterface $cache, 
  35.         private UrlGeneratorInterface $urlGenerator
  36.     ) {}
  37.     /**
  38.      * @param MultiStore $multiStore
  39.      * @param ProductHelper $productHelper
  40.      * @param SeoUrlHelper $seoUrlHelper
  41.      * 
  42.      * @return array{
  43.      *      banners: null|array<string,int|array<int,array<string,string|int>>>, 
  44.      *      smallBanners: array<string,array<string,string>>, 
  45.      *      mainProducts: array<int,array<string,mixed>>
  46.      * }
  47.      */
  48.     public function homepageData(MultiStore $multiStore, ProductHelper $productHelper, SeoUrlHelper $seoUrlHelper): array
  49.     {
  50.         // Helpers
  51.         $this->multiStore = $multiStore;
  52.         $this->productHelper = $productHelper;
  53.         $this->seoUrlHelper = $seoUrlHelper;
  54.         // Domain
  55.         $domain = $this->multiStore->getDomain();
  56.         return [
  57.             'banners'               => $this->getHeaderBanner($domain), 
  58.             'smallBanners'          => $this->getSmallBanners($domain), 
  59.             'mainProducts'          => $this->getMainProducts(), 
  60.             'featuredCategories'     => $this->getFeaturedCategories(), 
  61.         ];
  62.     }
  63.     /**
  64.      * @param Domain $domain
  65.      * 
  66.      * @return null|array{
  67.      *      interval: int, 
  68.      *      items: array<int,array<string,string|int>>, 
  69.      *      gtagEventItems: array<int,array<string,string|int>>
  70.      * }
  71.      */
  72.     private function getHeaderBanner(Domain $domain): ?array
  73.     {
  74.         /** @var Banner|null $banner */
  75.         $banner = $this->entityManager->getRepository(Banner::class)->findOneBy([
  76.             'domain'    => $domain, 
  77.             'type'      => Banner::BANNER_BAZAAR_MAIN_TYPE
  78.         ]);
  79.         if ( is_null($banner) || $banner->getBannerItems()->count() < 1 ) {
  80.             return null;
  81.         }
  82.         // Sorting
  83.         /** @var ArrayCollection<int, BannerItem> $bannerItemCollection */
  84.         $bannerItemCollection = $banner->getBannerItems();
  85.         $bannerItemCollection->matching(
  86.             Criteria::create()->orderBy([ 'sortIndex' => Criteria::ASC ])
  87.         );
  88.         $bannerItems = $gtagEventItems = [];
  89.         foreach ( $bannerItemCollection as $bannerItem ) {
  90.             if ( $bannerItem->getStartDate() != null && date_time_set($bannerItem->getStartDate(), 0, 0, 0, 1) > ( new \DateTime('now') )) {
  91.                 continue;
  92.             }
  93.             if ( $bannerItem->getEndDate() != null && date_time_set($bannerItem->getEndDate(), 23, 59, 59, 59) < ( new \DateTime('now') )) {
  94.                 continue;
  95.             }
  96.             if ( $bannerItem->getFilename() == '' || $bannerItem->getFilename() == null ) {
  97.                 continue;
  98.             }
  99.             $file = [
  100.                 'filename'      => $bannerItem->getFilename(), 
  101.                 'originalName'  => $bannerItem->getOriginalName() 
  102.             ];
  103.             $bannerItems[] = [
  104.                 'image'     => $this->imageService->of($file, BannerItem::BANNER_DIRECTORY)->resize(Image::BANNER_DESKTOP_WIDTH, Image::BANNER_DESKTOP_HEIGHT), 
  105.                 'link'      => $bannerItem->getLink(), 
  106.                 'parentId'  => $banner->getId(), 
  107.                 'itemId'    => $bannerItem->getId() 
  108.             ];
  109.             $gtagEventItems[] = [
  110.                 'item_id'           => "{$banner->getId()}_{$bannerItem->getId()}", 
  111.                 'item_name'         => $bannerItem->getLink(), 
  112.                 'index'             => $bannerItem->getSortIndex(), 
  113.                 'promotion_id'      => "{$banner->getId()}_{$bannerItem->getId()}", 
  114.                 'promotion_name'    => $bannerItem->getLink() 
  115.             ];
  116.         }
  117.         return [
  118.             'interval'          => $banner->getCountDown(), 
  119.             'items'             => $bannerItems, 
  120.             'gtagEventItems'    => $gtagEventItems
  121.         ];
  122.     }
  123.     /**
  124.      * @param Domain $domain
  125.      * 
  126.      * @return array{upper: array<string, string>, lower: array<string, string>}
  127.      */
  128.     private function getSmallBanners(Domain $domain): array
  129.     {
  130.         /** @var array{upper: array<string, string>, lower: array<string, string>} $data */
  131.         $data = [
  132.             'upper' => [], 
  133.             'lower' => []
  134.         ];
  135.         /** @var Banner|null $upperBanner */
  136.         $upperBanner = $this->entityManager->getRepository(Banner::class)->findOneBy([
  137.             'domain'    => $domain, 
  138.             'type'      => Banner::BANNER_BAZAAR_SMALL_UPPER_TYPE
  139.         ]);
  140.         if ( $upperBanner ) {
  141.             $data['upper']['display'] = $upperBanner->getDisplayType();
  142.             if ( $upperBanner->getDisplayType() == Banner::BANNER_DISPLAY_TYPE_BANNER ) {
  143.                 /** @var array<int,BannerItem> $upperBannerItems */
  144.                 $upperBannerItems = $upperBanner->getBannerItems()->getValues();
  145.                 // Sorting
  146.                 usort($upperBannerItems, function ($a, $b) {
  147.                     return $a->getSortIndex() <=> $b->getSortIndex();
  148.                 });
  149.                 // Filter
  150.                 $upperBannerItems = array_filter($upperBannerItems, function ($item) {
  151.                     $now = new \DateTime('now');
  152.                     $startDate = $item->getStartDate();
  153.                     $endDate = $item->getEndDate();
  154.                     return ( !$startDate || $startDate <= $now ) 
  155.                         && ( !$endDate || date_time_set($endDate, 23, 59, 59) >= $now )
  156.                     ;
  157.                 });
  158.                 // Image
  159.                 if ( count($upperBannerItems) > 0 ) {
  160.                     $upperBannerItem = $upperBannerItems[array_key_first($upperBannerItems)];
  161.                     $file = [
  162.                         'filename'      => $upperBannerItem->getFilename(),
  163.                         'originalName'  => $upperBannerItem->getOriginalName()
  164.                     ];
  165.                     $data['upper'] = [
  166.                         'image' => $this->imageService->of($file, BannerItem::BANNER_DIRECTORY)->resize(Image::SMALL_BANNER_DESKTOP_WIDTH, Image::SMALL_BANNER_DESKTOP_HEIGHT), 
  167.                         'link'  => $upperBannerItem->getLink(), 
  168.                         'title' => $upperBannerItem->getOriginalName()
  169.                     ];
  170.                 }
  171.             }
  172.         }
  173.         /** @var Banner|null $lowerBanner */
  174.         $lowerBanner = $this->entityManager->getRepository(Banner::class)->findOneBy([
  175.             'domain'    => $domain, 
  176.             'type'      => Banner::BANNER_BAZAAR_SMALL_LOWER_TYPE
  177.         ]);
  178.         if ( $lowerBanner ) {
  179.             $data['lower']['display'] = $lowerBanner->getDisplayType();
  180.             if ( $lowerBanner->getDisplayType() == Banner::BANNER_DISPLAY_TYPE_BANNER ) {
  181.                 /** @var array<int,BannerItem> $lowerBannerItems */
  182.                 $lowerBannerItems = $lowerBanner->getBannerItems()->getValues();
  183.                 // Sorting
  184.                 usort($lowerBannerItems, function ($a, $b) {
  185.                     return $a->getSortIndex() <=> $b->getSortIndex();
  186.                 });
  187.                 // Filter
  188.                 $lowerBannerItems = array_filter($lowerBannerItems, function ($item) {
  189.                     $now = new \DateTime('now');
  190.                     $startDate = $item->getStartDate();
  191.                     $endDate = $item->getEndDate();
  192.                     return ( !$startDate || $startDate <= $now ) 
  193.                         && ( !$endDate || date_time_set($endDate, 23, 59, 59) >= $now )
  194.                     ;
  195.                 });
  196.                 // Image
  197.                 if ( count($lowerBannerItems) > 0 ) {
  198.                     $lowerBannerItem = $lowerBannerItems[array_key_first($lowerBannerItems)];
  199.                     $file = [
  200.                         'filename'      => $lowerBannerItem->getFilename(),
  201.                         'originalName'  => $lowerBannerItem->getOriginalName()
  202.                     ];
  203.                     $data['lower'] = [
  204.                         'image' => $this->imageService->of($file, BannerItem::BANNER_DIRECTORY)->resize(Image::SMALL_BANNER_DESKTOP_WIDTH, Image::SMALL_BANNER_DESKTOP_HEIGHT), 
  205.                         'link'  => $lowerBannerItem->getLink(), 
  206.                         'title' => $lowerBannerItem->getOriginalName()
  207.                     ];
  208.                 }
  209.             }
  210.         }
  211.         return $data;
  212.     }
  213.     /**
  214.      * @return array<int,array<string,mixed>>
  215.      */
  216.     private function getMainProducts(): array 
  217.     {
  218.         $domain = $this->multiStore->getDomain();
  219.         $language = $this->multiStore->getLanguage();
  220.         $cacheKey = 'homepage.bazaar.main.products.v1.' . $domain->getId() . '.' . $language->getCode();
  221.         $cacheItem = $this->cache->getItem($cacheKey);
  222.         if ( $cacheItem->isHit() ) {
  223.             return (array)$cacheItem->get();
  224.         } else {
  225.             $placeholder = $this->imageService->of('placeholder.png', '')->resize(Image::PRODUCT_LIST_THUMB_WIDTH, Image::PRODUCT_LIST_THUMB_HEIGHT);
  226.             $productGroupProductData = $this->productHelper->getProductGroupProducts('homepage.bazaar.main', $domain);
  227.             $productGroupProducts = $productGroupProductData['productGroupProducts'];
  228.             $groupProductCodesAdded = $productGroupProductData['productGroupCodesAdded'];
  229.             $productsToDisplay = $productGroupProductData['productsToDisplay'];
  230.             $productGroupResults = $this->productHelper->getStructuredDataForProducts($productGroupProducts);
  231.             $mainProducts = $this->productHelper->convertStructuredDataToListViewData($this->seoUrlHelper, $productGroupResults, $placeholder);
  232.             // Fill in
  233.             if ( count($groupProductCodesAdded) < $productsToDisplay ) {
  234.                 $maxResults = $productsToDisplay - count($groupProductCodesAdded);
  235.                 // Already Added
  236.                 $productAlreadyAddedWhere = '';
  237.                 if (count($groupProductCodesAdded) > 0) {
  238.                     $productAlreadyAddedWhere = ' AND p.code NOT IN (' . implode(',', $groupProductCodesAdded) . ')';
  239.                 }
  240.                 $retailPage = $domain->getType() == 'retail';
  241.                 $notebookSaleProducts = $this->entityManager->createQuery("SELECT p
  242.                     FROM AtechNetCoreBundle:Product p
  243.                     LEFT JOIN AtechNetCoreBundle:ProductMeta pm WITH pm.id = (
  244.                         SELECT pm2.id FROM AtechNetCoreBundle:ProductMeta pm2 WHERE pm2.product = p.id AND pm2.domain = " . $domain->getId() . "
  245.                     )
  246.                     WHERE p.type = 52 AND pm.active = 1 AND p.available > 0 AND pm.orderable = 1 AND pm.listed = 1 AND p.qualityStatus = " . Product::QualityStatus_Bazaar . $productAlreadyAddedWhere . "
  247.                     ORDER BY pm.currentVatPrice ASC, p.updated DESC")
  248.                     ->setMaxResults($maxResults)
  249.                     ->getResult();
  250.                 $results = $this->productHelper->getStructuredDataForProducts($notebookSaleProducts);
  251.                 $mainProducts = array_merge($mainProducts, $this->productHelper->convertStructuredDataToListViewData($this->seoUrlHelper, $results, $placeholder));
  252.             }
  253.             foreach ( $mainProducts as $key => $value ) {
  254.                 $mainProducts[$key]['warrantyYear'] = $value['qualityStatusId'] == Product::QualityStatus_Bazaar ? 1 : $this->productService->getWarrantyForProductType($domain->getId(), $value['typeId'])['year'];
  255.             }
  256.             $cacheItem->set($mainProducts);
  257.             /** @todo */
  258.             $cacheItem->expiresAfter(900);
  259.             $this->cache->save($cacheItem);
  260.             return $mainProducts;
  261.         }
  262.     }
  263.     /**
  264.      * @return array<string,array<string,string|bool|int>>
  265.      */
  266.     private function getFeaturedCategories(): array 
  267.     {
  268.         $domain = $this->multiStore->getDomain();
  269.         $language = $this->multiStore->getLanguage();
  270.         $cacheKey = 'homepage.bazaar.featured.category.v1.' . $domain->getId() . '.' . $language->getCode();
  271.         $cacheItem = $this->cache->getItem($cacheKey);
  272.         if ( $cacheItem->isHit() ) {
  273.             return (array)$cacheItem->get();
  274.         } else {
  275.             $featuredCategoryUpper = $this->productHelper->getCategoryGroup($domain, CategoryGroup::CG_TYPE_BAZAAR_FEATURED_CATEGORIES_UPPER, $this->seoUrlHelper);
  276.             $featuredCategoryLower = $this->productHelper->getCategoryGroup($domain, CategoryGroup::CG_TYPE_BAZAAR_FEATURED_CATEGORIES_LOWER, $this->seoUrlHelper);
  277.             $featuredCategory = [];
  278.             if ( !empty($featuredCategoryUpper) ) {
  279.                 $featuredCategory['upper'] = $featuredCategoryUpper;
  280.             }
  281.             if (!empty($featuredCategoryLower)) {
  282.                 $featuredCategory['lower'] = $featuredCategoryLower;
  283.             }
  284.             $cacheItem->set($featuredCategory);
  285.             /** @todo */
  286.             $cacheItem->expiresAfter(1800);
  287.             $this->cache->save($cacheItem);
  288.             return $featuredCategory;
  289.         }
  290.     }
  291.     /**
  292.      * @param Domain $domain
  293.      * @param SeoUrlHelper $seoUrl
  294.      * 
  295.      * @return array<int,array<string,string>>
  296.      */
  297.     public function getHeaderPageList(Domain $domain, SeoUrlHelper $seoUrl): array
  298.     {
  299.         switch ( $domain->getLanguage()->getId() ) {
  300.             case Language::LANGUAGE_ID_HU: 
  301.                 return [
  302.                     [
  303.                         'link'  => $seoUrl->link('page', [ 'static_id' => 20 ]), 
  304.                         'title' => 'Rólunk'
  305.                     ], [
  306.                         'link'  => $this->urlGenerator->generate('review_list_hu'), 
  307.                         'title' => 'Referenciák'
  308.                     ], [
  309.                         'link'  => $seoUrl->link('page', [ 'static_id' => 26 ]), 
  310.                         'title' => 'GYIK'
  311.                     ], [
  312.                         'link'  => $seoUrl->link('page', [ 'static_id' => 202 ]), 
  313.                         'title' => 'Reklamáció és visszaküldés'
  314.                     ]
  315.                 ];
  316.             case Language::LANGUAGE_ID_SK:
  317.                 return [
  318.                     [
  319.                         'link'  => $seoUrl->link('page', [ 'static_id' => 50 ]), 
  320.                         'title' => 'O nás'
  321.                     ], [
  322.                         'link'  => $this->urlGenerator->generate('review_list_sk'), 
  323.                         'title' => 'Hodnotenia zákazníkov'
  324.                     ], [
  325.                         'link'  => $seoUrl->link('page', [ 'static_id' => 10 ]), 
  326.                         'title' => 'FAQ'
  327.                     ], [
  328.                         'link'  => $seoUrl->link('page', [ 'static_id' => 203 ]), 
  329.                         'title' => 'Vrátenie tovaru a reklamácie'
  330.                     ]
  331.                 ];
  332.             case Language::LANGUAGE_ID_CZ:
  333.                 return [
  334.                     [
  335.                         'link'  => $seoUrl->link('page', [ 'static_id' => 74 ]), 
  336.                         'title' => 'O nás'
  337.                     ], [
  338.                         'link'  => $this->urlGenerator->generate('review_list_cz'), 
  339.                         'title' => 'Hodnocení zákazníků'
  340.                     ], [
  341.                         'link'  => $seoUrl->link('page', [ 'static_id' => 59 ]), 
  342.                         'title' => 'FAQ'
  343.                     ], [
  344.                         'link'  => $seoUrl->link('page', [ 'static_id' => 204 ]),
  345.                         'title' => 'Odstoupení od smlouvy a reklamace'
  346.                     ]
  347.                 ];
  348.             case Language::LANGUAGE_ID_EN:
  349.                 return [
  350.                     [
  351.                         'link'  => $seoUrl->link('page', [ 'static_id' => 114 ]), 
  352.                         'title' => 'We Are Furbify'
  353.                     ], [
  354.                         'link'  => $seoUrl->link('page', [ 'static_id' => 99 ]), 
  355.                         'title' => 'FAQ'
  356.                     ], [
  357.                         'link' => $seoUrl->link('page', [ 'static_id' => 154 ]), 
  358.                         'title' => 'Shipping, Returns & Claims'
  359.                     ]
  360.                 ];
  361.         }
  362.         return [];
  363.     }
  364. }