108 lines
4.0 KiB
PHP
108 lines
4.0 KiB
PHP
<?php
|
|
|
|
namespace KupShop\LuigisBoxBundle\Recommenders;
|
|
|
|
use KupShop\CatalogBundle\ProductList\ProductCollection;
|
|
use KupShop\CatalogBundle\ProductList\ProductList;
|
|
use KupShop\LuigisBoxBundle\Api\RecommendersRequest;
|
|
use KupShop\RecommendersBundle\Recommenders\AbstractRecommender;
|
|
use KupShop\RecommendersBundle\Recommenders\IRecommender;
|
|
use KupShop\RecommendersBundle\Recommenders\RecommendersLocator;
|
|
use Query\Operator;
|
|
use Query\Product;
|
|
use Symfony\Component\HttpFoundation\RequestStack;
|
|
|
|
class LuigisBoxRecommender extends AbstractRecommender implements IRecommender
|
|
{
|
|
protected static string $type = 'luigisbox';
|
|
protected static string $name = 'Luigi\'s Box Recommender';
|
|
protected ?string $user_id;
|
|
|
|
public function __construct(
|
|
?RecommendersLocator $recommendersLocator,
|
|
protected RecommendersRequest $recommendersRequest,
|
|
protected ProductList $productList,
|
|
protected RequestStack $requestStack,
|
|
) {
|
|
$this->productList->applyDefaultFilterParams();
|
|
$this->user_id = $this->requestStack->getMainRequest()?->cookies->get('_lb');
|
|
|
|
parent::__construct($recommendersLocator);
|
|
}
|
|
|
|
public function execute(array $data, array $config): ProductCollection
|
|
{
|
|
$params = array_merge($config, $data, ['type' => $this::$type]);
|
|
|
|
$luigisParams = [];
|
|
$default = [
|
|
'user_id' => $this->user_id ?? '',
|
|
'size' => (int) $params['count'],
|
|
'hit_fields' => ['id', 'item_group_id', 'original_url', 'title'],
|
|
'mark_fallback_results' => true,
|
|
];
|
|
if (!empty($data['products'])) {
|
|
$default['item_ids'] = array_values(array_map('strval', $data['products']));
|
|
}
|
|
if (!empty($data['category'])) {
|
|
$category = (array) $data['category'];
|
|
if ($params['recommender_type'] == 'category') {
|
|
$default['item_ids'] = array_map('strval', $category);
|
|
} else {
|
|
$category = sqlQueryBuilder()->select('name')->from('sections')
|
|
->andWhere(Operator::inIntArray($category, 'id'))
|
|
->execute()->fetchFirstColumn();
|
|
if ($category) {
|
|
$default['recommendation_context']['category'] = ['values' => $category, 'operator' => 'or'];
|
|
}
|
|
}
|
|
}
|
|
$luigisParams[] = array_merge($default, ['recommendation_type' => $params['recommender_type']]);
|
|
|
|
if (!empty($params['fallback'])) {
|
|
$fallback = reset($params['fallback']);
|
|
if (($fallback['type'] == 'luigisbox') && (!empty($fallback['recommender_type']))) {
|
|
$luigisParams[] = array_merge($default, ['recommendation_type' => $fallback['recommender_type']]);
|
|
}
|
|
}
|
|
|
|
$searchResponse = $this->recommendersRequest->search($luigisParams);
|
|
$ids = [];
|
|
foreach ($searchResponse as $response) {
|
|
$hits = $response['hits'] ?? [];
|
|
foreach ($hits as $result) {
|
|
$id = (int) ($result['attributes']['item_group_id'][0] ?? $result['attributes']['id'][0] ?? $result['attributes']['original_url'] ?? $result['url'] ?? false);
|
|
if ($id) {
|
|
$ids[$id] = $id;
|
|
if (count($ids) >= $params['count']) {
|
|
break 2;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (empty($ids)) {
|
|
return new ProductCollection();
|
|
}
|
|
|
|
return $this->preparePreloadProductList($ids, $data)->getProducts();
|
|
}
|
|
|
|
protected function preparePreloadProductList(array $ids, array $data): ProductList
|
|
{
|
|
$productList = clone $this->productList;
|
|
$productList->andSpec(Product::productsIds($ids));
|
|
$productList->fetchImages($data['image'] ?? 'product_catalog');
|
|
|
|
return $productList;
|
|
}
|
|
|
|
public function getLogData()
|
|
{
|
|
return [
|
|
'request' => $this->recommendersRequest->request ?? null,
|
|
'response' => $this->recommendersRequest->response ?? null,
|
|
];
|
|
}
|
|
}
|