Files
kupshop/bundles/KupShop/RecommendersBundle/Twig/Components/EditableContent/Recommender.php
2025-08-02 16:30:27 +02:00

204 lines
5.9 KiB
PHP

<?php
declare(strict_types=1);
namespace KupShop\RecommendersBundle\Twig\Components\EditableContent;
use KupShop\CatalogBundle\ProductList\ProductCollection;
use KupShop\ComponentsBundle\Attributes\Blocek;
use KupShop\ComponentsBundle\Attributes\BlocekAttribute;
use KupShop\ComponentsBundle\Attributes\Component;
use KupShop\ComponentsBundle\Attributes\Version;
use KupShop\ComponentsBundle\GTM\PostMount\GTMDefaultData;
use KupShop\ComponentsBundle\Interfaces\Microdata;
use KupShop\ComponentsBundle\Twig\BaseComponent;
use KupShop\ComponentsBundle\Twig\DataProvider\LiveComponentRenderTrait;
use KupShop\ComponentsBundle\Twig\DataProvider\MicrodataProvider;
use KupShop\ContentBundle\Util\BlocekTypes;
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/EditableContent/Recommender/Recommender.1.html.twig', method: 'get')]
#[Component(1, [
new Version(1),
])]
#[Blocek(title: 'Recommender')]
class Recommender extends BaseComponent implements Microdata
{
use DefaultActionTrait;
use LiveComponentRenderTrait;
use GTMDefaultData;
#[Required]
public \KupShop\ComponentsBundle\GTM\Events\Products $gtmClass;
#[LiveProp]
public bool $isCarousel = true;
#[LiveProp]
public bool $showBtn = false;
#[LiveProp]
#[BlocekAttribute(default: 4, title: 'Počet produktů')]
public int $limit = 4;
#[LiveProp]
public ?int $defaultLimit;
#[LiveProp]
public bool $isHidden = true;
#[LiveProp]
public string $toggleText;
#[LiveProp]
#[BlocekAttribute(default: 'last-visited', title: 'Label', type: BlocekTypes::SELECT, options: 'getSelectValues')]
public string $label;
#[LiveProp]
public array $data = [];
#[LiveProp]
#[BlocekAttribute(title: 'Title')]
public string $title = '';
#[LiveProp(writable: true)]
public bool $lazy = false;
#[LiveProp]
#[BlocekAttribute(default: true)]
public bool $container = true;
#[LiveProp]
public string $title_class = 'h4';
protected array $recommender;
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
{
$this->defaultLimit = $this->limit;
}
public function __invoke(Request $request): ?Response
{
$data = json_decode($this->getRecommender()['data'] ?? '', true);
$cache = intval($data['cache'] ?? 3600);
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']);
}
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, 'count' => $this->limit];
$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)));
}
return '';
}
public static function getSelectValues(): array
{
return sqlQueryBuilder()
->select('position, label')
->from('recommenders')
->execute()
->fetchAllKeyValue();
}
}