<?php
declare(strict_types=1);
namespace AppBundle\Controller;
use AppBundle\Service\Geocoding\GeocodingSearchService;
use Exception;
use Pimcore\Db;
use Pimcore\Model\DataObject\JobOffer\Listing;
use Pimcore\Translation\Translator;
use Symfony\Component\HttpFoundation\Request;
class JobSearchController extends BaseController
{
private GeocodingSearchService $searchService;
public function __construct(GeocodingSearchService $searchService)
{
$this->searchService = $searchService;
}
public function defaultAction(Request $request, Translator $translator): array
{
$radius = (int) $request->get('radius');
$job = $request->get('job');
$city = $request->get('location');
$result = [];
if ($city && $radius) {
$result = $this->searchJobOffersWithLocation($job, $city, $radius, $translator);
} elseif ($job && !$city) {
$result = $this->searchJobOffers($job, $translator);
} else {
$result['message'] = $translator->trans('app.general.gemini.career.search.error.nocriteria');
}
return [
'job' => $job,
'city' => $city,
'radius' => $radius,
'jobOffers' => $result['jobOffers'] ?? null,
'message' => $result['message'] ?? null,
];
}
protected function searchJobOffers(string $job, Translator $translator): array
{
$jobOffers = new Listing();
$jobOffers->setOrderKey('title');
$jobOffers->setOrder('asc');
$jobOffers->setCondition('title LIKE :title', ['title' => '%' . $job . '%']);
if (0 == $jobOffers->getTotalCount()) {
$jobOffers = null;
$message = $translator->trans('app.general.gemini.career.search.error.noresults');
}
return [
'jobOffers' => $jobOffers,
'message' => $message,
];
}
protected function searchJobOffersWithLocation(string $job, string $city, int $radius, Translator $translator): array
{
$jobOffers = null;
$message = null;
try {
$cords = $this->getCityCords($city, $translator);
$resultsArray = $this->queryJobs($cords[0], $cords[1], $radius, $job, $translator);
$ids = $this->extractIds($resultsArray, $translator);
$jobOffers = $this->getJobOffers($ids, $translator);
} catch (Exception $ex) {
$message = $ex->getMessage();
}
return [
'jobOffers' => $jobOffers,
'message' => $message,
];
}
/**
* @throws Exception
*/
protected function queryJobs(float $lat, float $lon, int $radius, string $job = '', ?Translator $translator = null): array
{
$distanceString = '( 6371 * acos( cos( radians(' . $lat . ') ) * cos( radians( coordinates__latitude ) ) * cos( radians( coordinates__longitude ) - radians(' . $lon . ') ) + sin( radians(' . $lat . ') ) * sin( radians( coordinates__latitude ) ) ) )';
$sql = 'SELECT oo_id, coordinates__latitude, title, coordinates__longitude, ' . $distanceString . ' AS distance FROM object_query_1 '
. "WHERE title LIKE '%" . $job . "%' "
. 'AND ' . $distanceString . ' < ' . $radius . ' ';
$db = Db::get();
try {
$results = $db->fetchAll($sql);
} catch (Exception $ex) {
throw new Exception($translator->trans('app.general.gemini.career.search.error.searcherror1'), $ex->getCode(), $ex);
}
return $results;
}
/**
* @throws Exception
*/
protected function getCityCords(string $city, Translator $translator): array
{
$result = $this->searchService->search($city);
if (empty($result['error'])) {
return $result;
}
throw new Exception($translator->trans('app.general.gemini.career.search.error.searcherror2'));
}
/**
* @throws Exception
*/
protected function extractIds(array $array, Translator $translator): array
{
if ([] === $array) {
throw new Exception($translator->trans('app.general.gemini.career.search.error.noresults'));
}
$res = [];
foreach ($array as $item) {
$res[] = $item['oo_id'];
}
return $res;
}
/**
* @return array
* @throws Exception
*/
protected function getJobOffers(array $idsArray, Translator $translator): Listing
{
if ([] === $idsArray) {
throw new Exception($translator->trans('app.general.gemini.career.search.error.noresults'));
}
$jobOffers = new Listing();
$jobOffers->setOrderKey('title');
$jobOffers->setOrder('asc');
$jobOffers->setCondition('oo_id IN (:ids)', ['ids' => $idsArray]);
return $jobOffers;
}
}