<?php
namespace App\Service;
use App\Entity\Profile\Profile;
use App\Repository\ProfileRepository;
use App\Specification\ElasticSearch\ISpecification;
use App\Specification\Profile\ProfileIdINOrderedByINValues;
use App\Specification\Profile\ProfileIdNotIn;
use App\Specification\Profile\ProfileIsLocated;
use App\Specification\QueryModifier\ProfileOrderedByDistanceFromCoordinate;
use Happyr\DoctrineSpecification\Logic\AndX;
use Happyr\DoctrineSpecification\Query\QueryModifier;
class NearestProfiles
{
private array $result = [];
private int $limit = 0;
private Profile $profile;
public function __construct(
private ProfileRepository $profileRepository,
private ProfileList $profileList,
) {}
public function getNearestProfiles(Profile $profile, int $limit): array
{
$this->profile = $profile;
$this->limit = $limit;
if(null !== $profile->getMapCoordinate()->getLatitude() && null !== $profile->getMapCoordinate()->getLongitude()) {
$spec = new ProfileOrderedByDistanceFromCoordinate($profile->getMapCoordinate());
$this->fetch($spec);
}
// $spec = new ProfileIsLocated(null, null, null, [$profile->getStations()->first()]);
// $this->fetch($spec);
$spec = new ProfileIsLocated(null, null, null, [$profile->getStations()->toArray()]);
$this->fetch($spec);
$spec = new ProfileIsLocated($profile->getCity(), null, null, null);
$this->fetch($spec);
return count($this->result) ? $this->profileRepository->fetchListingByIds(new ProfileIdINOrderedByINValues($this->result)) : [];
}
private function fetch(ISpecification|QueryModifier $spec)
{
if(count($this->result) >= $this->limit) {
return;
}
$spec = new AndX(
$spec,
new ProfileIdNotIn(array_merge([$this->profile->getId()], $this->result)),
$this->profileList->getModerationSpecByFlag(),
$this->profileList->getActiveSpecByFlag(true),
);
$profileIds = $this->profileRepository->listIdMatchingSpec($spec, 0, $this->limit - count($this->result));
$this->result = array_merge($this->result, $profileIds);
}
}