Files
kupshop/bundles/KupShop/CatalogBundle/Search/GenericObjectsIndex.php
2025-08-02 16:30:27 +02:00

201 lines
6.8 KiB
PHP

<?php
declare(strict_types=1);
namespace KupShop\CatalogBundle\Search;
use KupShop\ContentBundle\Util\MenuUtil;
use KupShop\I18nBundle\Translations\BlocksTranslation;
use KupShop\I18nBundle\Translations\MenuLinksTranslation;
use KupShop\KupShopBundle\Context\LanguageContext;
use KupShop\KupShopBundle\Util\ArrayUtil;
use KupShop\SellerBundle\Utils\SellerUtil;
use Query\Operator;
use Query\QueryBuilder;
use Query\Translation;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Contracts\Service\Attribute\Required;
class GenericObjectsIndex
{
public const FIELDS = [
'id' => ['weight' => 0, 'type' => 'keyword'],
'name' => ['weight' => 10, 'type' => 'text'],
'name.no_spaces' => ['weight' => 2, 'type' => 'no_spaces'],
'descr' => ['weight' => 2, 'type' => 'text'],
'content' => ['weight' => 2, 'type' => 'text'],
'type' => ['weight' => 0, 'type' => 'text'],
];
protected ?SellerUtil $sellerUtil;
protected UrlGeneratorInterface $urlGenerator;
protected LanguageContext $languageContext;
public function getFields(): array
{
return static::FIELDS;
}
/**
* @return \Generator<array<array{
* id: int,
* name: string,
* descr?: string,
* content: string,
* type: GenericObjectType,
* url: string,
* image?: int,
* }>>
*/
public function getBatchedObjects(int $chunkSize = 1000): \Generator
{
return ArrayUtil::iterableChunk($this->getDataGenerators(), $chunkSize);
}
protected function getDataGenerators(\AppendIterator $iterator = new \AppendIterator()): \AppendIterator
{
if (findModule(\Modules::MENU)) {
$iterator->append(new \NoRewindIterator($this->pages()));
}
if (findModule(\Modules::SELLERS)) {
$iterator->append(new \NoRewindIterator($this->sellers()));
}
return $iterator;
}
protected function pages(): \Generator
{
$ids = sqlQueryBuilder()
->select('ml.id')
->from('menu_links', 'ml')
->andWhere(Operator::equals(['ml.type' => MenuUtil::TYPE_PAGE]))
->andWhere(Operator::equals(['ml.figure' => 'Y']))
->andWhere(Operator::equals(['ml.show_in_search' => 'Y']))
->groupBy('ml.id');
$qb = sqlQueryBuilder()
->select('ml.id', 'GROUP_CONCAT(b.content SEPARATOR "") as block_content')
->from('menu_links', 'ml')
->join('ml', 'blocks', 'b', 'b.id_root = ml.id_block')
->andWhere(Operator::inSubQuery('ml.id', $ids))
->andWhere(Translation::joinTranslatedFields(
MenuLinksTranslation::class,
function (QueryBuilder $qb, $columnName, $translatedField) {
if ($columnName == 'figure') {
$qb->andWhere(Operator::coalesce($translatedField, 'ml.figure')." != 'N'");
return false;
}
return true;
},
['name', 'url', 'figure']
))
->andWhere(
Translation::joinTranslatedFields(BlocksTranslation::class,
function (QueryBuilder $qb, $columnName, $translatedField) {
if ($translatedField) {
$qb->addSelect("GROUP_CONCAT({$translatedField} SEPARATOR '') as block_content");
} else {
$qb->addSelect('GROUP_CONCAT(b.content SEPARATOR "") as block_content');
}
},
['content'])
)
->andWhere(Operator::equals(['ml.type' => MenuUtil::TYPE_PAGE]))
->andWhere(Operator::equals(['ml.show_in_search' => 'Y']))
->groupBy('ml.id');
foreach ($qb->execute() as $row) {
if (!str_starts_with($row['url'], '/')) {
$row['url'] = "/{$row['url']}";
}
yield [
'id' => 'pages_'.$row['id'] ?? '',
'name' => $row['name'] ?? '',
'content' => strip_tags($page['block_content'] ?? ''),
'type' => GenericObjectType::Page,
'url' => $row['url'] ?? '',
];
}
}
protected function sellers(): \Generator
{
$permittedIds = null;
$isDefaultLanguageActive = $this->languageContext->getActiveId() === $this->languageContext->getDefaultId();
if (!$isDefaultLanguageActive) {
$permittedIds = $this->getPermittedSellerIDs($this->languageContext->getActiveId());
}
foreach ($this->sellerUtil->getSellers() as $sellerId => $seller) {
// Only index translated sellers
if ($permittedIds !== null && !in_array($sellerId, $permittedIds)) {
continue;
}
$content = '';
foreach (($seller['blocks'] ?? []) as $block) {
if ($blockContent = $block['content'] ?? null) {
$content .= $blockContent;
}
}
$content .= PHP_EOL.($seller['street'] ?? '').' '.($seller['number'] ?? '');
$content .= PHP_EOL.($seller['psc'] ?? '').' '.($seller['city'] ?? '');
$content .= PHP_EOL.($seller['email'] ?? '').' '.($seller['phone'] ?? '').' '.($seller['web'] ?? '');
$photoId = null;
if ($sellerPhotos = $seller['photos'] ?? null) {
$photoId = array_key_first($sellerPhotos);
}
$url = $seller['url'] ?: $this->urlGenerator->generate('shop_seller_seller_detail', ['id_seller' => $seller['id']]);
yield [
'id' => 'sellers_'.$seller['id'] ?? '',
'name' => $seller['title'] ?? '',
'content' => strip_tags($content),
'descr' => $seller['descr'] ?? null,
'type' => GenericObjectType::Seller,
'image' => $photoId,
'url' => $url,
];
}
}
protected function getPermittedSellerIDs(string $languageID): array
{
$qb = sqlQueryBuilder()
->select('id_seller')
->from('sellers_translations', 'st')
->andWhere(Operator::equals([
'st.id_language' => $languageID,
]));
return $qb->execute()->fetchFirstColumn();
}
#[Required]
final public function setSellerUtil(?SellerUtil $sellerUtil): void
{
$this->sellerUtil = $sellerUtil;
}
#[Required]
final public function setUrlGenerator(UrlGeneratorInterface $urlGenerator): void
{
$this->urlGenerator = $urlGenerator;
}
#[Required]
final public function setLanguageContext(LanguageContext $languageContext): void
{
$this->languageContext = $languageContext;
}
}