508 lines
16 KiB
PHP
508 lines
16 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace KupShop\CatalogElasticBundle\View;
|
|
|
|
use KupShop\CatalogBundle\CategorySort;
|
|
use KupShop\CatalogBundle\Entity\Producer;
|
|
use KupShop\CatalogBundle\Entity\Section;
|
|
use KupShop\CatalogBundle\Enum\Ordering;
|
|
use KupShop\CatalogBundle\ProductList\DynamicFilterAttributes;
|
|
use KupShop\CatalogBundle\Repository\ProducersRepository;
|
|
use KupShop\CatalogBundle\Repository\SectionsRepository;
|
|
use KupShop\CatalogBundle\Util\FilterUtil;
|
|
use KupShop\CatalogBundle\Util\IndexedFilterUtil;
|
|
use KupShop\CatalogBundle\Util\SectionUtil;
|
|
use KupShop\CatalogBundle\Util\SectionViewUtil;
|
|
use KupShop\CatalogBundle\View\CategoryRequestHandler;
|
|
use KupShop\ComponentsBundle\Twig\DataProvider\SectionDataProvider;
|
|
use KupShop\ComponentsBundle\View\ComponentsViewInterface;
|
|
use KupShop\ComponentsBundle\View\ComponentsViewTrait;
|
|
use KupShop\IndexedFilterBundle\Util\FilterUrlGenerator;
|
|
use KupShop\KupShopBundle\Util\StringUtil;
|
|
use KupShop\KupShopBundle\Views\View;
|
|
use Query\Operator;
|
|
use Symfony\Component\HttpFoundation\Request;
|
|
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
|
|
|
class SectionView extends View implements CategoryRequestHandler, ComponentsViewInterface
|
|
{
|
|
use ComponentsViewTrait;
|
|
|
|
protected $template = 'view/section.html.twig';
|
|
protected string $entrypoint = 'section';
|
|
|
|
protected ?int $categoryId = null;
|
|
protected ?int $producerId = null;
|
|
protected ?int $parameterValueId = null;
|
|
|
|
protected ?array $filterData = null;
|
|
protected \FilterParams $filterParams;
|
|
protected ?array $indexedFilterData = null;
|
|
|
|
protected Ordering $ordering;
|
|
protected int $page = 1;
|
|
|
|
private Section $section; // use getSection() to get the section
|
|
protected ?Producer $producer = null;
|
|
protected array $indexed_filter;
|
|
protected DynamicFilterAttributes $dynamicFilterAttributes;
|
|
private array $breadcrumbs;
|
|
|
|
public function __construct(
|
|
protected readonly IndexedFilterUtil $indexedFilterUtil,
|
|
protected readonly SectionViewUtil $categoryUtil,
|
|
protected readonly SectionDataProvider $sectionDataProvider,
|
|
protected readonly ProducersRepository $producersRepository,
|
|
protected readonly SectionsRepository $sectionsRepository,
|
|
protected readonly FilterUrlGenerator $filterUrlGenerator,
|
|
protected readonly SectionUtil $sectionUtil,
|
|
) {
|
|
$this->proxyCacheEnabled = findModule(\Modules::PROXY_CACHE, 'category');
|
|
}
|
|
|
|
public function getBodyVariables(): array
|
|
{
|
|
$body = parent::getBodyVariables();
|
|
|
|
$body['id_category'] = $this->categoryId;
|
|
$body['id_producer'] = $this->producerId;
|
|
|
|
$body['baseFilterParams'] = $this->createBaseFilterParams();
|
|
$body['filterParams'] = $this->filterParams = $this->createFilterParams();
|
|
$body['indexedFilter'] = $this->getIndexedFilter($this->filterParams);
|
|
|
|
$body['page'] = $this->page;
|
|
$body['ordering'] = $this->getOrdering();
|
|
|
|
$body['categorySort'] = match ($this->categoryId) {
|
|
null => null,
|
|
default => CategorySort::fromCategory($this->getSection(), $this->producerId),
|
|
};
|
|
|
|
$body['dynamicFilterConfiguration'] = $this->getDynamicFilterConfiguration();
|
|
$body['fetchAllFilters'] = $this->getFetchAllFilters();
|
|
|
|
return $body;
|
|
}
|
|
|
|
public function setProducerId($producerId)
|
|
{
|
|
$this->producerId = (int) $producerId;
|
|
$this->producer = $this->producersRepository->getProducerEntity($this->producerId);
|
|
|
|
if (!$this->producer) {
|
|
throw new NotFoundHttpException("Producer {$producerId} not found!");
|
|
}
|
|
|
|
$this->sectionDataProvider->addProducer($this->producer);
|
|
}
|
|
|
|
public function setParameterValueId($parameterValueId)
|
|
{
|
|
$this->parameterValueId = $parameterValueId;
|
|
}
|
|
|
|
public function setCategoryId($categoryId)
|
|
{
|
|
$this->categoryId = (int) $categoryId;
|
|
}
|
|
|
|
protected function getSection()
|
|
{
|
|
if (isset($this->section)) {
|
|
return $this->section;
|
|
}
|
|
// Fetch with parents - for breadcrumb navigation
|
|
$section = $this->sectionsRepository->findById($this->categoryId);
|
|
if (!$section) {
|
|
throw new NotFoundHttpException("Section {$this->categoryId} not found");
|
|
}
|
|
|
|
$this->sectionDataProvider->addSection($section);
|
|
|
|
return $this->section = $section;
|
|
}
|
|
|
|
public function getCorrectUrl(): ?string
|
|
{
|
|
if (!$this->categoryId && !$this->producerId) {
|
|
return path('kupshop_catalog_catalog_category');
|
|
}
|
|
|
|
$path = [];
|
|
|
|
if ($this->producerId) {
|
|
$producerPath = path('kupshop_catalog_catalog_producer', [
|
|
'id_producer' => $this->producerId,
|
|
'url_producer' => StringUtil::slugify($this->producer->getName()),
|
|
]);
|
|
$path[] = trim($producerPath, '/');
|
|
}
|
|
|
|
if ($this->categoryId > 0) {
|
|
$section = $this->getSection();
|
|
$sectionPath = ($this->producerId > 0 ? $section->getAutogeneratedUrl() : $section->getUrl());
|
|
$path[] = trim($sectionPath, '/');
|
|
}
|
|
|
|
// (LegacyUrlGenerator) automaticky přidá locale prefix
|
|
return path('page', ['path' => implode('/', $path).'/']);
|
|
}
|
|
|
|
protected function getCurrentUrl(Request $request): string
|
|
{
|
|
$currentUrl = parent::getCurrentUrl($request);
|
|
|
|
return $this->sectionUtil->removeFilterFromSectionUrl($request, $currentUrl);
|
|
}
|
|
|
|
public function getBreadcrumbsNew(): array
|
|
{
|
|
if (isset($this->breadcrumbs)) {
|
|
return $this->breadcrumbs;
|
|
}
|
|
|
|
$producer = $this->producer;
|
|
$section = $this->getSection();
|
|
|
|
$catProducer = $producer?->getId() ?? '';
|
|
$catProducerTitle = $producer?->getName() ?? '';
|
|
|
|
if ($section->getId() > 0) {
|
|
$breadcrumbs = [];
|
|
|
|
foreach ($section->getParents() as $parent) {
|
|
if ($parent->getId() === $section->getId()) {
|
|
// add active section
|
|
$breadcrumbs[] = [
|
|
'text' => $section->getNameShort() ?: $section->getName(),
|
|
'ID' => $parent->getId(),
|
|
'link' => path('page', ['path' => $section->getUrl()]),
|
|
];
|
|
|
|
continue;
|
|
}
|
|
|
|
$breadcrumbs[] = [
|
|
'text' => $parent->getNameShort() ?: $parent->getName(),
|
|
'link' => path('page', ['path' => $parent->getUrl()]),
|
|
'ID' => $parent->getId(),
|
|
];
|
|
}
|
|
|
|
if (!empty($catProducerTitle)) {
|
|
$home = sprintf(translate('getSections', 'functions')['catalogProducer'], $catProducerTitle);
|
|
|
|
array_unshift($breadcrumbs, [
|
|
'text' => $home,
|
|
'link' => createScriptURL([
|
|
'URL' => 'launch.php',
|
|
's' => 'category',
|
|
'IDpd' => $catProducer,
|
|
'producerTitle' => $catProducerTitle,
|
|
'TITLE' => $home,
|
|
]),
|
|
'ID' => '0',
|
|
]);
|
|
}
|
|
|
|
array_unshift($breadcrumbs, [
|
|
'text' => translate('getSections', 'functions')['home'],
|
|
'link' => createScriptURL([
|
|
'URL' => 'launch.php',
|
|
's' => 'index',
|
|
]),
|
|
]);
|
|
|
|
return $this->breadcrumbs = $breadcrumbs;
|
|
}
|
|
|
|
$breadcrumbs = [];
|
|
if ($catProducer) {
|
|
$home = sprintf(translate('getSections', 'functions')['catalogProducer'], $catProducerTitle);
|
|
} else {
|
|
$home = translate('getSections', 'functions')['catalog'];
|
|
}
|
|
|
|
if (!empty($home)) {
|
|
array_unshift($breadcrumbs, [
|
|
'text' => $home,
|
|
]);
|
|
}
|
|
|
|
array_unshift($breadcrumbs, [
|
|
'text' => translate('getSections', 'functions')['home'],
|
|
'link' => createScriptURL([
|
|
'URL' => 'launch.php',
|
|
's' => 'index',
|
|
]),
|
|
]);
|
|
|
|
return $breadcrumbs;
|
|
}
|
|
|
|
public function getWpjToolbar()
|
|
{
|
|
$wpjToolbar = [];
|
|
|
|
if ($this->categoryId > 0) {
|
|
$params = ['ID' => $this->categoryId];
|
|
if ($this->producerId > 0) {
|
|
$params['id_producer'] = $this->producerId;
|
|
}
|
|
$wpjToolbar = [
|
|
'url' => getAdminUrl('sections', $params),
|
|
'title' => 'Upravit sekci',
|
|
'translateUrl' => getAdminUrl('list', [
|
|
'type' => 'translateSections',
|
|
'iframe' => 1,
|
|
'objectIDs' => $this->categoryId,
|
|
]),
|
|
'translateTitle' => 'Překlad sekce',
|
|
];
|
|
} elseif ($this->producerId > 0) {
|
|
$wpjToolbar = [
|
|
'url' => getAdminUrl('producers', ['ID' => $this->producerId]),
|
|
'title' => 'Upravit výrobce',
|
|
'translateUrl' => getAdminUrl('list', [
|
|
'type' => 'translateProducers',
|
|
'iframe' => 1,
|
|
'objectIDs' => $this->producerId,
|
|
]),
|
|
'translateTitle' => 'Překlad výrobce',
|
|
];
|
|
}
|
|
$wpjToolbar['indexed_filter'] = $this->getIndexedFilterAdminUrl();
|
|
|
|
return array_merge(parent::getWpjToolbar(), $wpjToolbar);
|
|
}
|
|
|
|
public function getIndexedFilterAdminUrl()
|
|
{
|
|
$url = false;
|
|
if ($indexed_filter = $this->indexed_filter ?? null) {
|
|
if (!empty($indexed_filter['id'])) {
|
|
$params = ['ID' => $indexed_filter['id']];
|
|
} else {
|
|
$params = $indexed_filter + ['title' => $this->getTitle()];
|
|
}
|
|
$url = getAdminUrl('IndexedFiltersContent', $params);
|
|
}
|
|
|
|
return $url;
|
|
}
|
|
|
|
protected function getIndexedFilter(\FilterParams $filterParams)
|
|
{
|
|
if (!isset($this->indexed_filter)) {
|
|
$this->indexed_filter = $this->indexedFilterUtil->getIndexedFilter(
|
|
$this->categoryId,
|
|
$this->producerId,
|
|
$filterParams,
|
|
) ?: [];
|
|
}
|
|
|
|
return $this->indexed_filter;
|
|
}
|
|
|
|
public function getMetaTitle()
|
|
{
|
|
if (!empty($this->indexed_filter['meta_title'])) {
|
|
return $this->indexed_filter['meta_title'];
|
|
}
|
|
|
|
return $this->categoryUtil->createTitle(
|
|
$this->getSection(),
|
|
$this->producer,
|
|
$this->createFilterParams(),
|
|
$this->getDynamicFilterConfiguration(),
|
|
);
|
|
}
|
|
|
|
public function getTitle(): string
|
|
{
|
|
return $this->getMetaTitle();
|
|
}
|
|
|
|
public function getMetaDescription(): string
|
|
{
|
|
if (!empty($this->indexed_filter['meta_description'])) {
|
|
return $this->indexed_filter['meta_description'];
|
|
}
|
|
|
|
return $this->categoryUtil->createMetaDescription($this->getSection(), $this->producer);
|
|
}
|
|
|
|
public function createFilterParams(): \FilterParams
|
|
{
|
|
$filterParams = $this->createBaseFilterParams();
|
|
|
|
$filterData = FilterUtil::mergeIndexedAndDynamicFilterData(
|
|
$this->getDynamicFilterConfiguration(),
|
|
$this->filterData ?? [],
|
|
$this->indexedFilterData ?? [],
|
|
);
|
|
|
|
if (!empty($filterData)) {
|
|
$filter = new \Filter($filterParams);
|
|
$filter->setFilterData($filterData);
|
|
}
|
|
|
|
return $filterParams;
|
|
}
|
|
|
|
private function createBaseFilterParams(): \FilterParams
|
|
{
|
|
$filterParams = \FilterParams::createDefault();
|
|
|
|
if ($this->categoryId !== null) {
|
|
if ($this->categoryId === -1) {
|
|
$filterParams->setSearch($this->filterData['search'] ?? '');
|
|
}
|
|
|
|
if ($this->categoryId === 0 || $this->getSection()->displayProductsFromSubsections()) {
|
|
$filterParams->setSectionsFilter([$this->categoryId]);
|
|
} else {
|
|
$filterParams->setSections([$this->categoryId]);
|
|
}
|
|
}
|
|
|
|
if ($this->producerId) {
|
|
$filterParams->setProducers([$this->producerId]);
|
|
}
|
|
|
|
if ($this->parameterValueId) {
|
|
$parameterId = sqlQueryBuilder()
|
|
->select('id_parameter')
|
|
->from('parameters_list')
|
|
->andWhere(Operator::equals(['id' => $this->parameterValueId]))
|
|
->execute()
|
|
->fetchOne();
|
|
|
|
$filterParams->setParameter($parameterId, [$this->parameterValueId]);
|
|
}
|
|
|
|
return $filterParams;
|
|
}
|
|
|
|
private function getOrdering(): ?Ordering
|
|
{
|
|
if (!isset($this->ordering)) {
|
|
if (isset($this->categoryId)) {
|
|
return null;
|
|
}
|
|
|
|
if ($this->producer?->getOrderby()) {
|
|
return $this->ordering = new Ordering($this->producer->getOrderby(), $this->producer->getOrderdir());
|
|
}
|
|
}
|
|
|
|
return $this->ordering;
|
|
}
|
|
|
|
public function setOrdering(Ordering $ordering): void
|
|
{
|
|
$this->ordering = $ordering;
|
|
}
|
|
|
|
public function setPage(int $page): void
|
|
{
|
|
$this->page = $page;
|
|
}
|
|
|
|
public function setFilterData(array $filterData): self
|
|
{
|
|
$this->filterData = $filterData;
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function setParsedURLData($indexedFilterData)
|
|
{
|
|
$this->indexedFilterData = $indexedFilterData;
|
|
}
|
|
|
|
public function getDynamicFilterConfiguration(): DynamicFilterAttributes
|
|
{
|
|
return $this->dynamicFilterAttributes ??= $this->categoryUtil->getDynamicFilterConfiguration($this->getSection(), $this->producerId);
|
|
}
|
|
|
|
protected function getFetchAllFilters(): bool
|
|
{
|
|
$allFilters = FilterUtil::mergeIndexedAndDynamicFilterData(
|
|
$this->getDynamicFilterConfiguration(),
|
|
$this->filterData ?? [],
|
|
$this->indexedFilterData ?? [],
|
|
);
|
|
|
|
return !empty($allFilters);
|
|
}
|
|
|
|
public function setCampaign($campaign)
|
|
{
|
|
throw new NotFoundHttpException('Campaigns not supported!');
|
|
}
|
|
|
|
public function getCanonicalUrl(Request $request)
|
|
{
|
|
if ($this->producerId) {
|
|
$this->filterUrlGenerator->setIgnoreProducer(true);
|
|
}
|
|
|
|
if ($this->categoryId <= 0) {
|
|
$path = $request->getPathInfo();
|
|
} else {
|
|
$this->filterUrlGenerator->setSectionId($this->categoryId);
|
|
$this->filterUrlGenerator->setFilterParams($this->filterParams);
|
|
$this->filterUrlGenerator->setCategoryUrl($this->getCorrectUrl());
|
|
|
|
$indexedUrl = $this->filterUrlGenerator->generateIndexedUrl();
|
|
|
|
$path = $request->getSchemeAndHttpHost().$indexedUrl['url'];
|
|
}
|
|
|
|
// Hack? Maybe no ...
|
|
if (!$this->filterData && $page = $request->query->get('page')) {
|
|
$page = intval($page);
|
|
if ($page > 1) {
|
|
$path .= '?page='.$page;
|
|
}
|
|
}
|
|
|
|
return $path;
|
|
}
|
|
|
|
public function getCategoryId(): ?int
|
|
{
|
|
return $this->categoryId;
|
|
}
|
|
|
|
public function getProducerId(): ?int
|
|
{
|
|
return $this->producerId;
|
|
}
|
|
|
|
public function getTemplate(): string
|
|
{
|
|
return $this->getSection()->getTemplate() ?: $this->template;
|
|
}
|
|
|
|
public function getTemplates(): iterable
|
|
{
|
|
// List all shop templates in section
|
|
if (is_dir(__DIR__.'/../../../../../shop/twig/view/section')) {
|
|
foreach (new \FilesystemIterator(__DIR__.'/../../../../../shop/twig/view/section') as $file) {
|
|
yield 'view/section/'.$file->getFilename();
|
|
}
|
|
}
|
|
|
|
yield from [
|
|
$this->template,
|
|
'view/search.html.twig',
|
|
'block.productList.html.twig',
|
|
];
|
|
}
|
|
}
|