<?php
namespace Aqarmap\Bundle\TopSellerBundle\Service;
use Aqarmap\Bundle\FeatureToggleBundle\Service\FeatureToggleManager;
use Aqarmap\Bundle\ListingBundle\Service\Contracts\V4\LocationServiceInterface;
use Aqarmap\Bundle\ListingBundle\Service\LocationManager;
use Aqarmap\Bundle\TopSellerBundle\Model\TopSeller;
use Aqarmap\Bundle\UserBundle\Entity\User;
use Aqarmap\Bundle\UserBundle\Repository\UserRepository;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\ORMException;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use Psr\Log\LoggerInterface;
use Psr\Log\LogLevel;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Contracts\HttpClient\HttpClientInterface;
class TopSellerRetrievalService
{
public const TOP_SELLERS_LIMIT = 5;
/**
* @var UserRepository
*/
private $userRepository;
/**
* @var Client
*/
private $httpClient;
/**
* @var ParameterBagInterface
*/
private $parameterBag;
/**
* @var LoggerInterface
*/
private $logger;
/**
* @var LocationManager
*/
private $locationManager;
/**
* @var LocationServiceInterface
*/
private $locationService;
/**
* @var FeatureToggleManager
*/
private $featureToggleManager;
private HttpClientInterface $searchClient;
public function __construct(
EntityManagerInterface $em,
LoggerInterface $logger,
LocationManager $locationManager,
LocationServiceInterface $locationService,
ParameterBagInterface $parameterBag,
UserRepository $userRepository,
FeatureToggleManager $featureToggleManager,
HttpClientInterface $searchClient
) {
$this->userRepository = $userRepository;
$this->httpClient = new Client();
$this->logger = $logger;
$this->locationManager = $locationManager;
$this->parameterBag = $parameterBag;
$this->locationService = $locationService;
$this->featureToggleManager = $featureToggleManager;
$this->searchClient = $searchClient;
}
/**
* @return array
*/
public function retrieveTopSellers(TopSeller $topSeller, string $locale = 'ar')
{
$response = $this->getTopSellersResponseFromService($topSeller);
$data = $response ? $response->getBody() : '';
$topSellers = (array) json_decode($data, true);
return $this->getTopSellersData($topSellers, $locale);
}
/**
* @param TopSeller $topSeller
*/
private function getTopSellersResponseFromService($topSeller): ?\Psr\Http\Message\ResponseInterface
{
try {
if ($this->featureToggleManager->isDisabled('web.topsellers.enable')) {
return null;
}
$locationParents = $this->getLocationParents($topSeller->getLocation());
$response = $this->httpClient->request(
'GET',
$this->parameterBag->get('api_gateway.top_sellers.url').'/api/v1/top-sellers',
[
'query' => [
'location' => $topSeller->getLocation(),
'propertyType' => $topSeller->getPropertyType(),
'section' => $topSeller->getSection(),
'locationParents' => $locationParents,
'type' => $topSeller->getType(),
'hasPersonalPhoto' => $topSeller->hasPersonalPhoto(),
'hasCompanyLogo' => $topSeller->hasCompanyLogo(),
],
'timeout' => 1,
'connect_timeout' => 1,
]
);
} catch (GuzzleException|ORMException|\Exception $exception) {
$this->logger->log(LogLevel::ERROR, $exception->getMessage());
return null;
}
return $response;
}
/**
* @return array
*
* @throws ORMException
*/
private function getTopSellersData(array $topSellers, string $locale)
{
$topSellersData = [];
$counter = 0;
/** @var User $topSeller */
foreach ($this->userRepository->findBy(['id' => array_keys($topSellers)]) as $topSeller) {
$users = [$topSeller];
if ($topSeller->getChildren()->count()) {
$users = array_merge($users, $topSeller->getChildren()->toArray());
}
$topSellersData[$counter]['user'] = $topSeller;
$topSellersData[$counter]['liveListingsCount'] = $topSellers[$topSeller->getId()]['listingsCount'];
$topSellersData[$counter]['leadsCount'] = $topSeller->getClientServedCount();
$topSellersData[$counter]['location'] = isset($topSellers[$topSeller->getId()]['location']) ?
$this->locationManager->getLocation(['id' => $topSellers[$topSeller->getId()]['location']])->getTitle() : null;
$topSellersData[$counter]['servedLocations'] = $this->locationManager
->buildServingLeveledLocationsArray($users, 1, $locale);
$topSellersData[$counter]['isCompany'] = $topSellers[$topSeller->getId()]['isCompany'];
++$counter;
$activeListingSort = array_column($topSellersData, 'liveListingsCount');
array_multisort($activeListingSort, \SORT_DESC, $topSellersData);
}
return array_group_by($topSellersData, 'location');
}
/**
* @return array
*/
public function getTopSellerPersonalData(TopSeller $topSeller, string $locale = 'ar')
{
$topSellerResponse = $this->getTopSellersResponseFromService($topSeller);
$data = $topSellerResponse ? $topSellerResponse->getBody() : '';
$topSellers = (array) json_decode((string) $data, true);
$topSellersData = [];
$counter = 0;
/** @var User $topSeller */
foreach ($this->userRepository->findBy(['id' => array_keys($topSellers)]) as $topSeller) {
$topSellersData[$counter]['user'] = $topSeller;
$topSellersData[$counter]['isCompany'] = $topSellers[$topSeller->getId()]['isCompany'];
$topSellersData[$counter]['id'] = $topSellers[$topSeller->getId()]['user'];
$topSellersData[$counter]['numberOfActiveListing'] = $topSellers[$topSeller->getId()]['listingsCount'];
++$counter;
$activeListingSort = array_column($topSellersData, 'numberOfActiveListing');
array_multisort($activeListingSort, \SORT_DESC, $topSellersData);
}
return $topSellersData;
}
public function getTopSellersElasticResponse(Request $request): array
{
$request->query->set('aggregatedField', 'user');
$request->query->set('bucketsCount', self::TOP_SELLERS_LIMIT);
$topSellers = $this->searchClient->request(
'GET',
'/api/listing/histogram',
[
'query' => $request->query->all(),
]
);
return $topSellers->toArray();
}
private function getLocationParents($locationId): array
{
$locationParents = [];
if ($locationId) {
$locationParents = $this->locationService->getAllLocationParentsIds($locationId);
}
return $locationParents;
}
}