<?php
namespace App\AtechNet\CoreBundle\Helper\Furbify;
use App\AtechNet\CoreBundle\Entity\Basket;
use App\AtechNet\CoreBundle\Entity\BlogPage;
use App\AtechNet\CoreBundle\Entity\CategoryPage;
use App\AtechNet\CoreBundle\Entity\Coupon;
use App\AtechNet\CoreBundle\Entity\DomainPaymentType;
use App\AtechNet\CoreBundle\Entity\DomainShippingType;
use App\AtechNet\CoreBundle\Entity\Language;
use App\AtechNet\CoreBundle\Entity\Product;
use App\AtechNet\CoreBundle\Entity\Review;
use App\AtechNet\CoreBundle\Enum\PaymentType;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\HttpFoundation\Request;
use Twig\Environment;
class Module
{
public const CART_TIMEOUT = 2; // hours
private $url;
private $request;
private $translator;
private $internalTranslator;
private $multiStore;
private $productHelper;
private $cloudFlareApiConfig;
private $entityManager;
private $twig;
public function __construct($entityManager, Request $request, $productHelper, $cloudFlareApiConfig, $multiStore, $translator, $url, $internalTranslator, Environment $twig)
{
$this->url = $url;
$this->request = $request;
$this->translator = $translator;
$this->internalTranslator = $internalTranslator;
$this->multiStore = $multiStore;
$this->productHelper = $productHelper;
$this->cloudFlareApiConfig = $cloudFlareApiConfig;
$this->entityManager = $entityManager;
$this->twig = $twig;
}
/**
* @return string rendered view
* @throws \Exception
*/
public function widgetCart(): string
{
$data = [];
$domain = $this->multiStore->getDomain();
$data['currency'] = $domain->getCurrency();
$data['precision'] = $domain->getPricePrecision();
$data['total'] = 0;
$data['subTotal'] = 0;
$data['items'] = [];
$data['countItems'] = 0;
$placeholder = $this->getImage('placeholder.jpg', '')->resize(Image::PRODUCT_CART_THUMB_WIDTH, Image::PRODUCT_CART_THUMB_HEIGHT);
$cart = $this->entityManager->getRepository(Basket::class)->findOneBy(
[
'id' => $this->request->getSession()->get('cartId'),
'active' => true,
]
);
if ($cart) {
$expire = $cart->getUpdated()->add(new \DateInterval("PT" . self::CART_TIMEOUT . "H"));
if ($expire <= (new \DateTime('NOW'))) {
$cart->setActive(false);
$this->entityManager->flush();
} else {
foreach ($cart->getBasketItems() as $item) {
$product = $this->productHelper->getStructuredDataForProduct($item->getProduct(), 'cart');
if ($product && !in_array($product['id'], [Product::CASH_ON_DELIVERY_PRODUCT_ID, Product::MPL_PACKAGE_FEE_PRODUCT_ID])) {
$image = $placeholder;
if (is_object($product['images'])) {
$image = $this->getImage($product['images'], 'product/' . $product['code'])->resize(Image::PRODUCT_CART_THUMB_WIDTH, Image::PRODUCT_CART_THUMB_HEIGHT);
}
// Cross-sell Attribute Options
$crossSellAttributeOptions = CartHelper::getCrossSellAttributeOptionsByProductTypeId($product['productTypeId'], $domain->getId());
$options = [];
$optionPrice = 0;
foreach ($item->getItemAttributes() as $attribute) {
$option = $attribute->getAttributeOption();
$optionMeta = $option->getDomainMeta($domain);
if ($optionMeta) {
$optionValue = $option->getLongTitle($this->translator);
if (!$optionValue) {
$optionValue = $option->getTitle($this->translator);
}
$optionTitle = $option->getAttribute()->getTitle();
if ($optionMeta->isDiscounted()) {
$price = $optionMeta->getDomainVatDiscount();
} else {
$price = $optionMeta->getDomainVatPrice();
}
$optionModel = $optionHref = '';
/** @var Product $optionProduct */
$optionProduct = $option->getProduct();
if ($optionProduct) {
$optionModel = $optionProduct->getCode();
$optionHref = $this->url->link('product', [
'product_id' => $optionProduct->getId(),
'isBazaar' => $optionProduct->isBazaar()
]);
}
// If Attribute Option is for Cross-sell
if (isset($crossSellAttributeOptions[$option->getId()])) {
if (isset($crossSellAttributeOptions[$option->getId()]['percentPrice'])) {
$price = $domain->createVatPrice((($item->getPriceWithAttributesForDomainWithException($domain, $option) * $crossSellAttributeOptions[$option->getId()]['percentPrice']) / 100), 1.);
}
}
$options[] = [
'id' => $attribute->getId(),
'title' => $optionTitle,
'value' => $optionValue,
'price' => $price * $item->getQuantity(),
'model' => $optionModel,
'href' => $optionHref,
];
$optionPrice += $price;
}
}
if ($product['isDiscounted']) {
$price = $product['discountVatPrice'];
} else {
$price = $product['vatPrice'];
}
$data['items'][] = [
'id' => $item->getId(),
'productId' => $product['id'],
'model' => $product['code'],
'name' => ($product['vendor'] !== '' ? $product['vendor'] . ' ' : '') . $product['title'],
'image' => $image,
'quantity' => $item->getQuantity(),
'price' => $price * $item->getQuantity(),
'options' => $options,
'href' => $this->url->link('product', [
'product_id' => $product['id'],
'isBazaar' => $product['isBazaar'] ?? 0
]),
];
$data['subTotal'] += ($price + $optionPrice) * $item->getQuantity();
$data['countItems'] += (int)$item->getQuantity();
}
}
}
$data['expire'] = $expire->format('Y-m-d H:i:s');
}
$data['estimation'] = true;
$data['coupon'] = '';
$data['paymentCost'] = $data['shippingCost'] = $data['discount'] = 0;
if ($this->request->getSession()->has('checkout')) {
$checkout = $this->request->getSession()->get('checkout');
if (isset($checkout['shippingMethodId']) && (int)$checkout['shippingMethodId'] > 0) {
$shippingMethod = $this->entityManager->getRepository(DomainShippingType::class)->findOneBy([
'id' => $checkout['shippingMethodId'],
'domain' => $this->multiStore->getDomainId(),
]);
if ($shippingMethod) {
$data['shippingCost'] = ($shippingMethod->getFreeShipLimit() > $data['subTotal'] ? $shippingMethod->getPrice() : 0);
$data['estimation'] = false;
}
} else {
$shippingMethodWithHighestPrice = CartHelper::getShippingMethodWithHighestPriceForDomain($domain, $this->entityManager);
if ($shippingMethodWithHighestPrice) {
$data['shippingCost'] = (float)($shippingMethodWithHighestPrice->getFreeShipLimit() > (float)$data['subTotal'] ? $shippingMethodWithHighestPrice->getPrice() : 0);
$data['estimation'] = false;
}
}
if (isset($checkout['paymentMethodId']) && (int)$checkout['paymentMethodId'] > 0) {
$paymentMethod = $this->entityManager->getRepository(DomainPaymentType::class)->findOneBy([
'id' => $checkout['paymentMethodId'],
'domain' => $this->multiStore->getDomainId(),
]);
if ($paymentMethod) {
$data['paymentCost'] = $paymentMethod->getPrice();
}
}
if (isset($checkout['coupon']['discount']) && (int)$checkout['coupon']['discount'] > 0) {
$data['coupon'] = $checkout['coupon']['code'];
$coupon = $this->entityManager->getRepository(Coupon::class)->findOneBy([
'code' => $checkout['coupon']['code'],
'domain' => $domain,
]);
if ($coupon && $cart) {
// Set Email
if (!empty($checkout['email'])) {
$cart->setEmail($checkout['email']);
} else {
$cart->setEmail(null);
}
$isCouponValidForBasket = CartHelper::isCouponValidForBasket($coupon, $cart, $this->entityManager);
if ($isCouponValidForBasket) {
$data['discount'] = $isCouponValidForBasket;
}
}
}
if (isset($checkout['3_percent_discount']) && $checkout['3_percent_discount']) {
if ($cart) {
$data['discount'] = CartHelper::getPercentDiscountForBasket($cart, 3);
$data['three_percent_partner_discount'] = true;
}
}
if (isset($checkout['paymentMethodTypeId']) && (int)$checkout['paymentMethodTypeId'] == PaymentType::CashOnDelivery->value) {
$domainPaymentType = $this->entityManager->getRepository(DomainPaymentType::class)->findOneBy(
[
'domain' => $this->multiStore->getDomainId(),
'type' => $checkout['paymentMethodTypeId'],
]
);
if ($domainPaymentType) {
$data['cashOnDeliveryProductItem'] = [
'title' => $this->translator->trans('Cash on delivery'),
'price' => $domainPaymentType->getPrice(),
];
}
}
} else {
$shippingMethodWithHighestPrice = CartHelper::getShippingMethodWithHighestPriceForDomain($domain, $this->entityManager);
if ($shippingMethodWithHighestPrice) {
$data['shippingCost'] = ($shippingMethodWithHighestPrice->getFreeShipLimit() > $data['subTotal'] ? $shippingMethodWithHighestPrice->getPrice() : 0);
$data['estimation'] = false;
}
}
$data['total'] = $data['subTotal'] + $data['shippingCost'] + $data['paymentCost'] - $data['discount'];
return $this->twig->render('AtechNetCoreBundle/Module/cart.html.twig', $data);
}
/**
* @return string rendered view
*/
public function blockPopularLink(): string
{
$data = [];
$data['links'] = [];
if ($this->multiStore->getDomain()->getId() == 1) {
$data['links'][] = [
'text' => $this->translator->trans('Computer monitor'),
'href' => $this->url->link('category', [
'path' => 6,
]),
];
} else {
$data['links'][] = [
'text' => $this->translator->trans('Computer monitor'),
'href' => $this->url->link('category', [
'path' => 78,
]),
];
}
$data['links'][] = [
'text' => $this->translator->trans('For camera systems'),
'href' => $this->url->link('search', [
'ft' => '60',
]),
];
$data['links'][] = [
'text' => 'HDMI Monitor',
'href' => $this->url->link('search', [
'ft' => '44',
]),
];
$data['links'][] = [
'text' => $this->translator->trans('Used laptops'),
'href' => $this->url->link('search', [
'ft' => '52',
]),
];
$data['links'][] = [
'text' => $this->translator->trans('User gamer computers'),
'href' => $this->url->link('search', [
'ft' => '60,52',
'fb' => 'gamer',
]),
];
$data['links'][] = [
'text' => $this->translator->trans('Complete computer'),
'href' => $this->url->link('search', [
'ft' => '107',
]),
];
$data['links'][] = [
'text' => $this->translator->trans('Desktop PC full configuration'),
'href' => $this->url->link('search', [
'ft' => '60',
]),
];
$data['links'][] = [
'text' => 'USB wifi',
'href' => $this->url->link('search', [
'fa[105]' => '773',
]),
];
$data['links'][] = [
'text' => 'ddr 4gb',
'href' => $this->url->link('search', [
'fa[3]' => ['74'],
]),
];
$data['links'][] = [
'text' => $this->translator->trans('With webcam'),
'href' => $this->url->link('search', [
'fa[19]' => '571,574,763,1481',
]),
];
$data['links'][] = [
'text' => $this->translator->trans('For loan'),
'href' => $this->url->link('search', [
'ft' => '60',
]),
];
$data['links'][] = [
'text' => $this->translator->trans('Power supply'),
'href' => $this->url->link('search', [
'ft' => '65',
]),
];
$data['links'][] = [
'text' => $this->translator->trans('With touch display'),
'href' => $this->url->link('search', [
'fa[139]' => '1295',
]),
];
if ($this->multiStore->getDomain()->getId() == 1) {
$data['links'][] = [
'text' => $this->translator->trans('Renewed notebooks'),
'href' => $this->url->link('category', [
'path' => 5,
]), // HU 56
];
$data['links'][] = [
'text' => $this->translator->trans('Renewed PC'),
'href' => $this->url->link('category', [
'path' => 4,
]), // HU 48
];
$data['links'][] = [
'text' => $this->translator->trans('Notebook docking station'),
'href' => $this->url->link('category', [
'path' => 9,
]), // HU 46
];
} else {
$data['links'][] = [
'text' => $this->translator->trans('Renewed notebooks'),
'href' => $this->url->link('category', [
'path' => 56,
]), // HU 56
];
$data['links'][] = [
'text' => $this->translator->trans('Renewed PC'),
'href' => $this->url->link('category', [
'path' => 48,
]), // HU 48
];
$data['links'][] = [
'text' => $this->translator->trans('Notebook docking station'),
'href' => $this->url->link('category', [
'path' => 46,
]), // HU 46
];
}
return $this->twig->render('AtechNetCoreBundle/Module/popularLink.html.twig', $data);
}
/**
* @param string $view
* @return string rendered view
*/
public function blockTestimonial(string $view = 'full', $checkShowAtHomePage = false): string
{
$data = [];
$data['view'] = $view;
$data['testimonials'] = [];
$reviewCount = $this->testimonialCount();
$data['reviewCount'] = $reviewCount;
$multiStore = $this->multiStore;
$languageIds = [$multiStore->getDefaultLanguageId()];
if ($multiStore->getDefaultLanguageId() == Language::LANGUAGE_ID_CZ) {
$languageIds[] = Language::LANGUAGE_ID_SK;
} elseif ($multiStore->getDefaultLanguageId() == Language::LANGUAGE_ID_SK) {
$languageIds[] = Language::LANGUAGE_ID_CZ;
}
$reviews = $this->entityManager->createQuery("SELECT DISTINCT r
FROM AtechNetCoreBundle:Review r
LEFT JOIN r.surveyMedias surveyMedias
WHERE r.language IN(:languageIds) AND r.type = :type AND r.approved = :approved AND surveyMedias IS NOT NULL AND surveyMedias.approved = 1" . ($checkShowAtHomePage ? " AND r.showAtHomepage = 1" : "") . "
ORDER BY r.created DESC")
->setParameters([
'languageIds' => $languageIds,
'type' => Review::TYPE_PRODUCT,
'approved' => true,
])
->setMaxResults(5)
->getResult()
;
$fs = new Filesystem();
foreach ($reviews as $review) {
$key = $review->getName() . '-' . $review->getCreated()->format('YmdHi');
$text = mb_strlen($review->getText()) > 200 ? mb_substr($review->getText(), 0, 196) . ' ...' : $review->getText();
$data['testimonials'][$key] = [
'name' => $review->getName(),
'text' => $text,
'rating' => $review->getStars(),
'order' => $review->getOrder(),
'created' => $review->getCreated(),
'product' => $review->getProduct(),
];
$data['testimonials'][$key]['images'] = [];
foreach ($review->getSurveyMedias() as $reviewSurveyMedia) {
$surveyMedia = $reviewSurveyMedia->getSurveyMedia();
if ($reviewSurveyMedia->isApproved() && !isset($data['testimonials'][$key]['images'][$surveyMedia->getId()]) && count($data['testimonials'][$key]['images']) < 1) {
$thumbDirPath = 'storage/image/reviews/' . $review->getId() . '/thumbs';
$popupDirPath = 'storage/image/reviews/' . $review->getId() . '/popup';
$blockDirPath = 'storage/image/reviews/' . $review->getId() . '/block';
$thumbPath = $thumbDirPath . '/' . $surveyMedia->getFilename();
$popupPath = $popupDirPath . '/' . $surveyMedia->getFilename();
$blockPath = $blockDirPath . '/' . $surveyMedia->getFilename();
if (!$fs->exists($thumbDirPath)) {
$fs->mkdir($thumbDirPath, 0755);
}
if (!$fs->exists($popupDirPath)) {
$fs->mkdir($popupDirPath, 0755);
}
if (!$fs->exists($blockDirPath)) {
$fs->mkdir($blockDirPath, 0755);
}
if (!$fs->exists($thumbPath)) {
$resize = new ResizeImage($surveyMedia->getDirectory() . '/' . $surveyMedia->getFilename());
$resize->resizeTo(Image::PRODUCT_VIEW_THUMB_WIDTH, Image::PRODUCT_VIEW_THUMB_HEIGHT, 'maxWidth');
$resize->saveImage($thumbPath);
}
if (!$fs->exists($popupPath)) {
$resize = new ResizeImage($surveyMedia->getDirectory() . '/' . $surveyMedia->getFilename());
$resize->resizeTo(Image::PRODUCT_VIEW_POPUP_WIDTH, Image::PRODUCT_VIEW_POPUP_HEIGHT);
$resize->saveImage($popupPath);
}
// Cloudflare Image
$imagePath = $reviewSurveyMedia->getCdnUrl('ProductViewThumb');
// Internal Image
if ($imagePath == '' && !$fs->exists($blockPath)) {
$resize = new ResizeImage($surveyMedia->getDirectory() . '/' . $surveyMedia->getFilename());
$resize->resizeTo(Image::PRODUCT_VIEW_THUMB_WIDTH, Image::PRODUCT_VIEW_THUMB_HEIGHT, 'crop');
$resize->saveImage($blockPath);
$imagePath = '/' . $blockPath;
} elseif ($imagePath == '') {
$imagePath = '/' . $thumbPath;
}
$data['testimonials'][$key]['images'][$surveyMedia->getId()] = $imagePath;
}
}
}
return $this->twig->render('AtechNetCoreBundle/Module/testimonial.html.twig', $data);
}
public function testimonialCount()
{
$multiStore = $this->multiStore;
$languageIds = [$multiStore->getDefaultLanguageId()];
if ($multiStore->getDefaultLanguageId() == Language::LANGUAGE_ID_CZ) {
$languageIds[] = Language::LANGUAGE_ID_SK;
} elseif ($multiStore->getDefaultLanguageId() == Language::LANGUAGE_ID_SK) {
$languageIds[] = Language::LANGUAGE_ID_CZ;
}
return $this->entityManager->createQuery("SELECT COUNT(r.id)
FROM AtechNetCoreBundle:Review r
WHERE r.language IN(:language) AND r.type = :type AND r.approved = :approved")
->setParameters([
'language' => $languageIds,
'type' => Review::TYPE_PRODUCT,
'approved' => true,
])
->getSingleScalarResult()
;
}
/**
* @return string rendered view
*/
public function blockBlogCategory(): string
{
$data = [];
$domain = $this->multiStore->getDomain();
$language = $this->multiStore->getDefaultLanguage();
$blogCategoryId = 0;
if ($this->request->attributes->get('blogCategoryId')) {
$blogCategoryId = (int)$this->request->attributes->get('blogCategoryId');
} elseif ($this->request->attributes->get('blogId')) {
$blog = $this->entityManager->getRepository(BlogPage::class)->findOneById($this->request->attributes->get('blogId'));
if ($blog) {
$blogCategory = $blog->getCategoryPage();
if ($blogCategory) {
$blogCategoryId = $blogCategory->getId();
}
}
}
$data['categories'] = [];
$categories = $this->entityManager->getRepository(CategoryPage::class)->findBy([
'domain' => $domain->getId(),
'published' => 1,
'type' => CategoryPage::TYPE_BLOG,
]);
foreach ($categories as $category) {
$meta = $category->getMetaByLanguage($language);
$blogCount = $this->entityManager->getRepository(BlogPage::class)->count([
'categoryPage' => $category->getId(),
]);
if ($meta && !in_array($meta->getTitle(), ['blog', 'BLOG']) && $blogCount > 0) {
$data['categories'][] = [
'id' => $category->getId(),
'title' => $meta->getTitle(),
'href' => $this->url->link('blog_category', [
'blog_category_id' => $category->getId(),
]),
];
}
}
$data['blogCategoryId'] = $blogCategoryId;
return $this->twig->render('AtechNetCoreBundle/Module/blogCategory.html.twig', $data);
}
/**
* @return string rendered view
*/
public function blockBlogTagCloud(): string
{
$domain = $this->multiStore->getDomain();
$connection = $this->entityManager->getConnection();
$tags = $connection->executeQuery("SELECT t.name, t.slug, COUNT(DISTINCT bp.blog_page_id ) AS total FROM pages_blog_tags AS bp JOIN tag AS t ON t.id = bp.tag_id WHERE t.language_id = ? GROUP BY t.name", [$domain->getLanguage()->getId()])->fetchAll();
if (!empty($tags)) {
$minimumCount = $maximumCount = false;
$minimumFontSize = 12;
$maximumFontSize = 24;
foreach ($tags as $tag) {
if (!$minimumCount) {
$minimumCount = (int)$tag['total'];
} elseif ($minimumCount > (int)$tag['total']) {
$minimumCount = (int)$tag['total'];
}
if (!$maximumCount) {
$maximumCount = (int)$tag['total'];
} elseif ($maximumCount < (int)$tag['total']) {
$maximumCount = (int)$tag['total'];
}
}
foreach ($tags as $index => $tag) {
$tags[$index]['fontSize'] = (((int)$tag['total'] / (count($tags) - 1)) * ($maximumFontSize - $minimumFontSize)) + $minimumFontSize;
}
}
return $this->twig->render('AtechNetCoreBundle/Module/blogTagCloud.html.twig', [
'tags' => $tags,
]);
}
/**
* @return string rendered view
*/
public function blockBlogFeatured(?string $link): string
{
$data = [];
$domain = $this->multiStore->getDomain();
$language = $this->multiStore->getDefaultLanguage();
$blogs = $this->entityManager->getRepository(BlogPage::class)->getFeaturedBlogs($language);
if (count($blogs)) {
foreach ($blogs as $blog) {
$blogMeta = $blog->getBlogPage()->getMetaByLanguage($language);
$blogCategoryId = $blogMeta->getCategoryPage() && $blogMeta->getCategoryPage()->getId() > 0 ? $blogMeta->getCategoryPage()->getId() : $this->multiStore->getBlogCategoryIdByDomainId($domain->getId());
$data['blogs'][] = [
'id' => $blog->getBlogPage()->getId(),
'title' => $blogMeta->getTitle(),
'link' => $this->url->link('blog', [
'blog_id' => $blog->getBlogPage()->getId(),
'blog_category_id' => $blogCategoryId,
]),
'active' => !is_null($link) && $blogMeta->getLink() == $link,
];
}
$data['featuredBlog'] = true;
}
return $this->twig->render('AtechNetCoreBundle/Module/blogFeatured.html.twig', $data);
}
/**
* @param object|string $photo
* @param string $directory
* @return Image
*/
protected function getImage($photo, string $directory = 'product'): Image
{
return new Image($this->cloudFlareApiConfig, $photo, $directory);
}
}