<?php
namespace App\AtechNet\CoreBundle\Service\Furbify;
use App\AtechNet\CoreBundle\Entity\Banner;
use App\AtechNet\CoreBundle\Entity\BannerItem;
use App\AtechNet\CoreBundle\Entity\CategoryGroup;
use App\AtechNet\CoreBundle\Entity\Domain;
use App\AtechNet\CoreBundle\Entity\Language;
use App\AtechNet\CoreBundle\Entity\Product;
use App\AtechNet\CoreBundle\Helper\Furbify\Image;
use App\AtechNet\CoreBundle\Helper\Furbify\MultiStore;
use App\AtechNet\CoreBundle\Helper\Furbify\ProductHelper;
use App\AtechNet\CoreBundle\Helper\Furbify\SeoUrlHelper;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Criteria;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Contracts\Cache\CacheInterface;
use Symfony\Contracts\Cache\ItemInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
use Psr\Cache\CacheItemPoolInterface;
class BazaarService
{
/** @var MultiStore */
private MultiStore $multiStore;
/** @var ProductHelper */
private ProductHelper $productHelper;
/** @var SeoUrlHelper */
private SeoUrlHelper $seoUrlHelper;
public function __construct(
private ImageService $imageService,
private ProductService $productService,
private EntityManagerInterface $entityManager,
// private TranslatorInterface $translator,
private CacheItemPoolInterface $cache,
private UrlGeneratorInterface $urlGenerator
) {}
/**
* @param MultiStore $multiStore
* @param ProductHelper $productHelper
* @param SeoUrlHelper $seoUrlHelper
*
* @return array{
* banners: null|array<string,int|array<int,array<string,string|int>>>,
* smallBanners: array<string,array<string,string>>,
* mainProducts: array<int,array<string,mixed>>
* }
*/
public function homepageData(MultiStore $multiStore, ProductHelper $productHelper, SeoUrlHelper $seoUrlHelper): array
{
// Helpers
$this->multiStore = $multiStore;
$this->productHelper = $productHelper;
$this->seoUrlHelper = $seoUrlHelper;
// Domain
$domain = $this->multiStore->getDomain();
return [
'banners' => $this->getHeaderBanner($domain),
'smallBanners' => $this->getSmallBanners($domain),
'mainProducts' => $this->getMainProducts(),
'featuredCategories' => $this->getFeaturedCategories(),
];
}
/**
* @param Domain $domain
*
* @return null|array{
* interval: int,
* items: array<int,array<string,string|int>>,
* gtagEventItems: array<int,array<string,string|int>>
* }
*/
private function getHeaderBanner(Domain $domain): ?array
{
/** @var Banner|null $banner */
$banner = $this->entityManager->getRepository(Banner::class)->findOneBy([
'domain' => $domain,
'type' => Banner::BANNER_BAZAAR_MAIN_TYPE
]);
if ( is_null($banner) || $banner->getBannerItems()->count() < 1 ) {
return null;
}
// Sorting
/** @var ArrayCollection<int, BannerItem> $bannerItemCollection */
$bannerItemCollection = $banner->getBannerItems();
$bannerItemCollection->matching(
Criteria::create()->orderBy([ 'sortIndex' => Criteria::ASC ])
);
$bannerItems = $gtagEventItems = [];
foreach ( $bannerItemCollection as $bannerItem ) {
if ( $bannerItem->getStartDate() != null && date_time_set($bannerItem->getStartDate(), 0, 0, 0, 1) > ( new \DateTime('now') )) {
continue;
}
if ( $bannerItem->getEndDate() != null && date_time_set($bannerItem->getEndDate(), 23, 59, 59, 59) < ( new \DateTime('now') )) {
continue;
}
if ( $bannerItem->getFilename() == '' || $bannerItem->getFilename() == null ) {
continue;
}
$file = [
'filename' => $bannerItem->getFilename(),
'originalName' => $bannerItem->getOriginalName()
];
$bannerItems[] = [
'image' => $this->imageService->of($file, BannerItem::BANNER_DIRECTORY)->resize(Image::BANNER_DESKTOP_WIDTH, Image::BANNER_DESKTOP_HEIGHT),
'link' => $bannerItem->getLink(),
'parentId' => $banner->getId(),
'itemId' => $bannerItem->getId()
];
$gtagEventItems[] = [
'item_id' => "{$banner->getId()}_{$bannerItem->getId()}",
'item_name' => $bannerItem->getLink(),
'index' => $bannerItem->getSortIndex(),
'promotion_id' => "{$banner->getId()}_{$bannerItem->getId()}",
'promotion_name' => $bannerItem->getLink()
];
}
return [
'interval' => $banner->getCountDown(),
'items' => $bannerItems,
'gtagEventItems' => $gtagEventItems
];
}
/**
* @param Domain $domain
*
* @return array{upper: array<string, string>, lower: array<string, string>}
*/
private function getSmallBanners(Domain $domain): array
{
/** @var array{upper: array<string, string>, lower: array<string, string>} $data */
$data = [
'upper' => [],
'lower' => []
];
/** @var Banner|null $upperBanner */
$upperBanner = $this->entityManager->getRepository(Banner::class)->findOneBy([
'domain' => $domain,
'type' => Banner::BANNER_BAZAAR_SMALL_UPPER_TYPE
]);
if ( $upperBanner ) {
$data['upper']['display'] = $upperBanner->getDisplayType();
if ( $upperBanner->getDisplayType() == Banner::BANNER_DISPLAY_TYPE_BANNER ) {
/** @var array<int,BannerItem> $upperBannerItems */
$upperBannerItems = $upperBanner->getBannerItems()->getValues();
// Sorting
usort($upperBannerItems, function ($a, $b) {
return $a->getSortIndex() <=> $b->getSortIndex();
});
// Filter
$upperBannerItems = array_filter($upperBannerItems, function ($item) {
$now = new \DateTime('now');
$startDate = $item->getStartDate();
$endDate = $item->getEndDate();
return ( !$startDate || $startDate <= $now )
&& ( !$endDate || date_time_set($endDate, 23, 59, 59) >= $now )
;
});
// Image
if ( count($upperBannerItems) > 0 ) {
$upperBannerItem = $upperBannerItems[array_key_first($upperBannerItems)];
$file = [
'filename' => $upperBannerItem->getFilename(),
'originalName' => $upperBannerItem->getOriginalName()
];
$data['upper'] = [
'image' => $this->imageService->of($file, BannerItem::BANNER_DIRECTORY)->resize(Image::SMALL_BANNER_DESKTOP_WIDTH, Image::SMALL_BANNER_DESKTOP_HEIGHT),
'link' => $upperBannerItem->getLink(),
'title' => $upperBannerItem->getOriginalName()
];
}
}
}
/** @var Banner|null $lowerBanner */
$lowerBanner = $this->entityManager->getRepository(Banner::class)->findOneBy([
'domain' => $domain,
'type' => Banner::BANNER_BAZAAR_SMALL_LOWER_TYPE
]);
if ( $lowerBanner ) {
$data['lower']['display'] = $lowerBanner->getDisplayType();
if ( $lowerBanner->getDisplayType() == Banner::BANNER_DISPLAY_TYPE_BANNER ) {
/** @var array<int,BannerItem> $lowerBannerItems */
$lowerBannerItems = $lowerBanner->getBannerItems()->getValues();
// Sorting
usort($lowerBannerItems, function ($a, $b) {
return $a->getSortIndex() <=> $b->getSortIndex();
});
// Filter
$lowerBannerItems = array_filter($lowerBannerItems, function ($item) {
$now = new \DateTime('now');
$startDate = $item->getStartDate();
$endDate = $item->getEndDate();
return ( !$startDate || $startDate <= $now )
&& ( !$endDate || date_time_set($endDate, 23, 59, 59) >= $now )
;
});
// Image
if ( count($lowerBannerItems) > 0 ) {
$lowerBannerItem = $lowerBannerItems[array_key_first($lowerBannerItems)];
$file = [
'filename' => $lowerBannerItem->getFilename(),
'originalName' => $lowerBannerItem->getOriginalName()
];
$data['lower'] = [
'image' => $this->imageService->of($file, BannerItem::BANNER_DIRECTORY)->resize(Image::SMALL_BANNER_DESKTOP_WIDTH, Image::SMALL_BANNER_DESKTOP_HEIGHT),
'link' => $lowerBannerItem->getLink(),
'title' => $lowerBannerItem->getOriginalName()
];
}
}
}
return $data;
}
/**
* @return array<int,array<string,mixed>>
*/
private function getMainProducts(): array
{
$domain = $this->multiStore->getDomain();
$language = $this->multiStore->getLanguage();
$cacheKey = 'homepage.bazaar.main.products.v1.' . $domain->getId() . '.' . $language->getCode();
$cacheItem = $this->cache->getItem($cacheKey);
if ( $cacheItem->isHit() ) {
return (array)$cacheItem->get();
} else {
$placeholder = $this->imageService->of('placeholder.png', '')->resize(Image::PRODUCT_LIST_THUMB_WIDTH, Image::PRODUCT_LIST_THUMB_HEIGHT);
$productGroupProductData = $this->productHelper->getProductGroupProducts('homepage.bazaar.main', $domain);
$productGroupProducts = $productGroupProductData['productGroupProducts'];
$groupProductCodesAdded = $productGroupProductData['productGroupCodesAdded'];
$productsToDisplay = $productGroupProductData['productsToDisplay'];
$productGroupResults = $this->productHelper->getStructuredDataForProducts($productGroupProducts);
$mainProducts = $this->productHelper->convertStructuredDataToListViewData($this->seoUrlHelper, $productGroupResults, $placeholder);
// Fill in
if ( count($groupProductCodesAdded) < $productsToDisplay ) {
$maxResults = $productsToDisplay - count($groupProductCodesAdded);
// Already Added
$productAlreadyAddedWhere = '';
if (count($groupProductCodesAdded) > 0) {
$productAlreadyAddedWhere = ' AND p.code NOT IN (' . implode(',', $groupProductCodesAdded) . ')';
}
$retailPage = $domain->getType() == 'retail';
$notebookSaleProducts = $this->entityManager->createQuery("SELECT p
FROM AtechNetCoreBundle:Product p
LEFT JOIN AtechNetCoreBundle:ProductMeta pm WITH pm.id = (
SELECT pm2.id FROM AtechNetCoreBundle:ProductMeta pm2 WHERE pm2.product = p.id AND pm2.domain = " . $domain->getId() . "
)
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 . "
ORDER BY pm.currentVatPrice ASC, p.updated DESC")
->setMaxResults($maxResults)
->getResult();
$results = $this->productHelper->getStructuredDataForProducts($notebookSaleProducts);
$mainProducts = array_merge($mainProducts, $this->productHelper->convertStructuredDataToListViewData($this->seoUrlHelper, $results, $placeholder));
}
foreach ( $mainProducts as $key => $value ) {
$mainProducts[$key]['warrantyYear'] = $value['qualityStatusId'] == Product::QualityStatus_Bazaar ? 1 : $this->productService->getWarrantyForProductType($domain->getId(), $value['typeId'])['year'];
}
$cacheItem->set($mainProducts);
/** @todo */
$cacheItem->expiresAfter(900);
$this->cache->save($cacheItem);
return $mainProducts;
}
}
/**
* @return array<string,array<string,string|bool|int>>
*/
private function getFeaturedCategories(): array
{
$domain = $this->multiStore->getDomain();
$language = $this->multiStore->getLanguage();
$cacheKey = 'homepage.bazaar.featured.category.v1.' . $domain->getId() . '.' . $language->getCode();
$cacheItem = $this->cache->getItem($cacheKey);
if ( $cacheItem->isHit() ) {
return (array)$cacheItem->get();
} else {
$featuredCategoryUpper = $this->productHelper->getCategoryGroup($domain, CategoryGroup::CG_TYPE_BAZAAR_FEATURED_CATEGORIES_UPPER, $this->seoUrlHelper);
$featuredCategoryLower = $this->productHelper->getCategoryGroup($domain, CategoryGroup::CG_TYPE_BAZAAR_FEATURED_CATEGORIES_LOWER, $this->seoUrlHelper);
$featuredCategory = [];
if ( !empty($featuredCategoryUpper) ) {
$featuredCategory['upper'] = $featuredCategoryUpper;
}
if (!empty($featuredCategoryLower)) {
$featuredCategory['lower'] = $featuredCategoryLower;
}
$cacheItem->set($featuredCategory);
/** @todo */
$cacheItem->expiresAfter(1800);
$this->cache->save($cacheItem);
return $featuredCategory;
}
}
/**
* @param Domain $domain
* @param SeoUrlHelper $seoUrl
*
* @return array<int,array<string,string>>
*/
public function getHeaderPageList(Domain $domain, SeoUrlHelper $seoUrl): array
{
switch ( $domain->getLanguage()->getId() ) {
case Language::LANGUAGE_ID_HU:
return [
[
'link' => $seoUrl->link('page', [ 'static_id' => 20 ]),
'title' => 'Rólunk'
], [
'link' => $this->urlGenerator->generate('review_list_hu'),
'title' => 'Referenciák'
], [
'link' => $seoUrl->link('page', [ 'static_id' => 26 ]),
'title' => 'GYIK'
], [
'link' => $seoUrl->link('page', [ 'static_id' => 202 ]),
'title' => 'Reklamáció és visszaküldés'
]
];
case Language::LANGUAGE_ID_SK:
return [
[
'link' => $seoUrl->link('page', [ 'static_id' => 50 ]),
'title' => 'O nás'
], [
'link' => $this->urlGenerator->generate('review_list_sk'),
'title' => 'Hodnotenia zákazníkov'
], [
'link' => $seoUrl->link('page', [ 'static_id' => 10 ]),
'title' => 'FAQ'
], [
'link' => $seoUrl->link('page', [ 'static_id' => 203 ]),
'title' => 'Vrátenie tovaru a reklamácie'
]
];
case Language::LANGUAGE_ID_CZ:
return [
[
'link' => $seoUrl->link('page', [ 'static_id' => 74 ]),
'title' => 'O nás'
], [
'link' => $this->urlGenerator->generate('review_list_cz'),
'title' => 'Hodnocení zákazníků'
], [
'link' => $seoUrl->link('page', [ 'static_id' => 59 ]),
'title' => 'FAQ'
], [
'link' => $seoUrl->link('page', [ 'static_id' => 204 ]),
'title' => 'Odstoupení od smlouvy a reklamace'
]
];
case Language::LANGUAGE_ID_EN:
return [
[
'link' => $seoUrl->link('page', [ 'static_id' => 114 ]),
'title' => 'We Are Furbify'
], [
'link' => $seoUrl->link('page', [ 'static_id' => 99 ]),
'title' => 'FAQ'
], [
'link' => $seoUrl->link('page', [ 'static_id' => 154 ]),
'title' => 'Shipping, Returns & Claims'
]
];
}
return [];
}
}