234 lines
6.5 KiB
PHP
234 lines
6.5 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace KupShop\RecommendersBundle\Twig\Components;
|
|
|
|
use KupShop\CatalogBundle\ProductList\ProductCollection;
|
|
use KupShop\ComponentsBundle\Attributes\Component;
|
|
use KupShop\ComponentsBundle\Attributes\Version;
|
|
use KupShop\ComponentsBundle\GTM\PostMount\GTMPlaceholdersData;
|
|
use KupShop\ComponentsBundle\Interfaces\Microdata;
|
|
use KupShop\ComponentsBundle\Twig\BaseComponent;
|
|
use KupShop\ComponentsBundle\Twig\DataProvider\LiveComponentRenderTrait;
|
|
use KupShop\ComponentsBundle\Twig\DataProvider\MicrodataProvider;
|
|
use KupShop\KupShopBundle\Context\CacheContext;
|
|
use KupShop\KupShopBundle\Util\Contexts;
|
|
use KupShop\KupShopBundle\Util\StringUtil;
|
|
use KupShop\RecommendersBundle\Util\RecommendersUtil;
|
|
use Symfony\Component\HttpFoundation\Request;
|
|
use Symfony\Component\HttpFoundation\Response;
|
|
use Symfony\Contracts\Service\Attribute\Required;
|
|
use Symfony\Contracts\Translation\TranslatorInterface;
|
|
use Symfony\UX\LiveComponent\Attribute\AsLiveComponent;
|
|
use Symfony\UX\LiveComponent\Attribute\LiveAction;
|
|
use Symfony\UX\LiveComponent\Attribute\LiveListener;
|
|
use Symfony\UX\LiveComponent\Attribute\LiveProp;
|
|
use Symfony\UX\LiveComponent\DefaultActionTrait;
|
|
use Symfony\UX\TwigComponent\Attribute\PostMount;
|
|
use Symfony\UX\TwigComponent\Attribute\PreMount;
|
|
|
|
#[AsLiveComponent(template: '@Recommenders/components/Recommender/Recommender.1.html.twig', method: 'get')]
|
|
#[Component(1, [
|
|
new Version(1),
|
|
])]
|
|
class Recommender extends BaseComponent implements Microdata
|
|
{
|
|
use DefaultActionTrait;
|
|
use LiveComponentRenderTrait;
|
|
use GTMPlaceholdersData;
|
|
|
|
#[Required]
|
|
public \KupShop\ComponentsBundle\GTM\Events\Products $gtmClass;
|
|
|
|
#[LiveProp]
|
|
public bool $isCarousel = true;
|
|
#[LiveProp]
|
|
public bool $isSquareItemCarousel = false;
|
|
|
|
#[LiveProp]
|
|
public bool $showBtn = false;
|
|
#[LiveProp]
|
|
public ?int $limit = null;
|
|
#[LiveProp]
|
|
public ?int $defaultLimit = null;
|
|
#[LiveProp]
|
|
public bool $isHidden = true;
|
|
#[LiveProp]
|
|
public string $toggleText;
|
|
#[LiveProp]
|
|
public string $label;
|
|
#[LiveProp(writable: true)]
|
|
public array $data = [];
|
|
#[LiveProp]
|
|
public string $title = '';
|
|
#[LiveProp(writable: true)]
|
|
public bool $lazy = true;
|
|
#[LiveProp]
|
|
public bool $container = true;
|
|
#[LiveProp]
|
|
public string $title_class = 'h4';
|
|
#[LiveProp]
|
|
public string $additional_class = '';
|
|
#[LiveProp]
|
|
public bool $useOuterscopeIdentifier = true;
|
|
|
|
protected array $recommender;
|
|
public ?string $propsCacheKey = null;
|
|
|
|
protected ProductCollection $productList;
|
|
|
|
public function __construct(protected RecommendersUtil $recommendersUtil, private readonly TranslatorInterface $translator)
|
|
{
|
|
$this->toggleText = $this->translator->trans('recommender.show', [], 'products');
|
|
}
|
|
|
|
#[PostMount]
|
|
public function postMount(): void
|
|
{
|
|
if ($this->limit) {
|
|
$this->defaultLimit = $this->limit;
|
|
}
|
|
}
|
|
|
|
public function __invoke(Request $request): ?Response
|
|
{
|
|
$cache = $this->getRecommenderTTL();
|
|
|
|
if ($cache > 0) {
|
|
return $this->createResponse($request, $cache);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
#[PreMount]
|
|
public function preMount(array $data): array
|
|
{
|
|
if ($id_product = ($data['id_product'] ?? null)) {
|
|
$data['data']['product'] = $id_product;
|
|
unset($data['id_product']);
|
|
}
|
|
if ($id_category = ($data['id_category'] ?? null)) {
|
|
$data['data']['section'] = (array) $id_category;
|
|
unset($data['id_category']);
|
|
}
|
|
|
|
$data['propsCacheKey'] ??= serialize($data);
|
|
|
|
return $data;
|
|
}
|
|
|
|
public function getRecommender(): array
|
|
{
|
|
if (!isset($this->recommender)) {
|
|
$this->recommender = $this->recommendersUtil->getRecommenderByLabel($this->label) ?: [];
|
|
}
|
|
|
|
return $this->recommender;
|
|
}
|
|
|
|
public function getDataRecommender()
|
|
{
|
|
return json_encode([
|
|
'label' => $this->label,
|
|
'data' => $this->data,
|
|
]);
|
|
}
|
|
|
|
public function getCount(): ?int
|
|
{
|
|
if ($this->lazy) {
|
|
return null;
|
|
}
|
|
|
|
return $this->getProductList()->count();
|
|
}
|
|
|
|
public function getProductList(): ?ProductCollection
|
|
{
|
|
if ($this->lazy) {
|
|
return null;
|
|
}
|
|
|
|
if (!isset($this->productList)) {
|
|
$data = ['label' => $this->label, 'data' => $this->data];
|
|
$this->productList = $this->recommendersUtil->getRecommendersProducts($data);
|
|
}
|
|
|
|
return $this->productList;
|
|
}
|
|
|
|
#[LiveListener('recommenderLoad')]
|
|
public function load()
|
|
{
|
|
$this->lazy = false;
|
|
}
|
|
|
|
public function initMicrodata(): array
|
|
{
|
|
// Aby to mělo svůj scope
|
|
return [MicrodataProvider::RECOMMENDER => []];
|
|
}
|
|
|
|
#[LiveAction]
|
|
public function toggleAction(): void
|
|
{
|
|
if ($this->isHidden) {
|
|
$this->toggleText = $this->translator->trans('recommender.hide', [], 'products');
|
|
$this->isHidden = false;
|
|
$this->limit = 100;
|
|
} else {
|
|
$this->toggleText = $this->translator->trans('recommender.show', [], 'products');
|
|
$this->isHidden = true;
|
|
$this->limit = $this->defaultLimit;
|
|
}
|
|
}
|
|
|
|
public function getGTMPlaceholders(): array
|
|
{
|
|
return ['item_list_name' => 'recommender', 'item_list_id' => $this->getRecommender()['id'] ?? ''];
|
|
}
|
|
|
|
public function getTrackingData(): string
|
|
{
|
|
if ($this->getProductList()) {
|
|
return htmlentities(json_encode($this->gtmClass->getPushData($this), JSON_NUMERIC_CHECK | JSON_HEX_APOS));
|
|
}
|
|
|
|
return '';
|
|
}
|
|
|
|
private function getRecommenderTTL(): int
|
|
{
|
|
$data = json_decode($this->getRecommender()['data'] ?? '', true);
|
|
|
|
return intval($data['cache'] ?? 3600);
|
|
}
|
|
|
|
public function getCacheKey(): string
|
|
{
|
|
if ($this->lazy || !$this->propsCacheKey) {
|
|
return '_skip';
|
|
}
|
|
|
|
$cacheKey = [
|
|
Contexts::get(CacheContext::class)->getKey([
|
|
CacheContext::TYPE_TEXT,
|
|
CacheContext::TYPE_PRICE,
|
|
CacheContext::TYPE_AVAILABILITY,
|
|
]),
|
|
static::class,
|
|
$this->version,
|
|
$this->propsCacheKey,
|
|
];
|
|
|
|
return StringUtil::slugify(implode('_', $cacheKey));
|
|
}
|
|
|
|
public function getCacheTTL(): int
|
|
{
|
|
return $this->lazy || !$this->propsCacheKey ? 0 : $this->getRecommenderTTL();
|
|
}
|
|
}
|