<?php
namespace App\Controller;
use App\Entity\Filter;
use App\Form\Type\FilterType;
use App\Service\FilterJobsService;
use App\Service\PoleEmploiService;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Serializer\SerializerInterface;
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
class FilterController extends AbstractController
{
const TEMPORARY_FOLDER = '/tmp';
/**
* @var PoleEmploiService
*/
private PoleEmploiService $poleEmploiService;
/**
* @var FilterJobsService
*/
private FilterJobsService $filterJobsService;
/**
* @var SerializerInterface
*/
private SerializerInterface $serializer;
/**
* @var Filesystem
*/
private Filesystem $filesystem;
/**
* @param PoleEmploiService $poleEmploiService
* @param FilterJobsService $filterJobsService
* @param SerializerInterface $serializer
* @param Filesystem $filesystem
*/
public function __construct(
PoleEmploiService $poleEmploiService,
FilterJobsService $filterJobsService,
SerializerInterface $serializer,
Filesystem $filesystem
) {
$this->poleEmploiService = $poleEmploiService;
$this->filterJobsService = $filterJobsService;
$this->serializer = $serializer;
$this->filesystem = $filesystem;
}
/**
* @param Request $request
* @return Response
* @throws ClientExceptionInterface
* @throws \Psr\Container\ContainerExceptionInterface
* @throws \Psr\Container\NotFoundExceptionInterface
* @throws \Symfony\Contracts\HttpClient\Exception\DecodingExceptionInterface
* @throws \Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface
* @throws \Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface
* @throws \Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface
*/
public function filterByRomeCodesAndKeywords(Request $request): Response
{
// Create form with FilterType and handle the request
$form = $this->createForm(FilterType::class)
->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
/** @var Filter $data */
$data = $form->getData();
try {
// Fetch jobs from ROME codes
$jobs = $this->poleEmploiService->getJobByRomeCode($data->getRomeCodes());
} catch (\Exception $exception) {
// Set the flash message if error
$this->addFlash('error', $exception->getMessage());
// Get back with the flash message
return $this->redirectToRoute($request->attributes->get('_route'));
}
if (!empty($data->getKeywords())) {
try {
// Filter jobs with keywords
$filteredJobsByKeywords = $this->filterJobsService->filterJobsByKeywords(
$jobs['resultats'],
$data->getKeywords()
);
} catch (\Exception $exception) {
// Set the flash message if error
$this->addFlash('error', $exception->getMessage());
// Get back with the flash message
return $this->redirectToRoute($request->attributes->get('_route'));
}
}
if (!empty($data->getCompanyName())) {
try {
// Filter jobs with keywords
$filteredJobsByCompanyName = $this->filterJobsService->filterJobsByCompanyName(
$jobs['resultats'],
$data->getCompanyName()
);
} catch (\Exception $exception) {
// Set the flash message if error
$this->addFlash('error', $exception->getMessage());
// Get back with the flash message
return $this->redirectToRoute($request->attributes->get('_route'));
}
}
// Merge the two results arrays
$merge = $this->mergeJobsByKeywordsAndCompanyName(
$filteredJobsByKeywords ?? [],
$filteredJobsByCompanyName ?? []
);
// Add the file name into the variable
$download['jobs'] = [
'file' => $this->saveTemporaryFileResult($this->serializeIntoCsv($jobs['resultats'])),
'entries' => \count($jobs['resultats']),
];
// Add the file name into the variable
$download['merge'] = [
'file' => $this->saveTemporaryFileResult($this->serializeIntoCsv($merge)),
'entries' => \count($merge),
];
}
// Render the form
return $this->render('jobs/result.html.twig', [
'form' => $form->createView(),
'download' => $download ?? [],
]);
}
/**
* @param string $content
* @return string
*/
private function saveTemporaryFileResult(string $content): string
{
$filePath = uniqid();
$fileName = sprintf('%s/%s', self::TEMPORARY_FOLDER, $filePath);
$this->filesystem->dumpFile($fileName, $content);
return $filePath;
}
/**
* @param array $result
* @return string
*/
private function serializeIntoCsv(array $result): string
{
return $this->serializer->serialize($result, 'csv');
}
/**
* @param array $jobsByKeywords
* @param array $jobsByCompanyName
* @return array
*/
private function mergeJobsByKeywordsAndCompanyName(array $jobsByKeywords = [], array $jobsByCompanyName = []): array
{
return array_values(array_replace_recursive(
array_column($jobsByKeywords, null, 'id'),
array_column($jobsByCompanyName, null, 'id')
));
}
}