<?phpnamespace App\Controller\ThemesWebsite\Whileresume\Application;use App\Entity\Core\Users;use App\Entity\Cvs\Candidates;use App\Entity\Cvs\CandidatesHasExperiences;use App\Entity\Cvs\CandidatesHasProjects;use App\Entity\Cvs\CandidatesHasServices;use App\Entity\Cvs\CandidatesHasSkills;use App\Entity\Cvs\Jobs;use App\Entity\Cvs\JobsHasLikes;use App\Form\Core\UsersType;use App\Form\Cvs\JobsForm;use App\Form\Cvs\JobsFrForm;use App\Services\Core\RequestData;use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache;use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;use Symfony\Component\EventDispatcher\EventDispatcherInterface;use Symfony\Component\HttpFoundation\Request;use Symfony\Component\HttpFoundation\Response;use Symfony\Component\Routing\Annotation\Route;use Symfony\Component\HttpFoundation\Cookie;use Symfony\Component\HttpFoundation\JsonResponse;use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;use Doctrine\ORM\EntityManagerInterface;class JobsController extends AbstractController{ private $rd; private $em; public function __construct(RequestData $rd, EntityManagerInterface $em ) { $this->rd = $rd; $this->em = $em; } public function new(Request $request): Response { $locale = $request->getLocale(); $user = $this->getUser(); $jobClass = JobsForm::class; if($locale == "fr") { $jobClass = JobsFrForm::class; } $job = new Jobs(); $form = $this->createForm($jobClass, $job); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { $job->setSlug("0"); $job->setLocale($locale); $job->setValidation(false); $job->setVerification(false); $job->setOnline(false); $job->setEnterprise(null); $job->setUser($user); $this->em->persist($job); $this->em->flush(); if($job->getSlug() != "0") { $job->setSlug($this->generateSlug($job->getId())); $this->em->persist($job); $this->em->flush(); } if($locale !== "en") { return $this->redirectToRoute('locale_cvs_application_job_new_confirm',['_locale' => $locale]); } return $this->redirectToRoute('cvs_application_job_new_confirm'); } return $this->render('application/whileresume/application/jobs/new_'.$locale.'.html.twig',[ 'form' => $form->createView(), ]); } private function generateSlug(int $id): string { $letters = 'abcdefghijklmnopqrstuvwxyz'; $random = ''; for ($i = 0; $i < 6; $i++) { $random .= $letters[random_int(0, 25)]; } return $random . '-' . $id; } public function show(Request $request, $slug): Response { $locale = $request->getLocale(); $job = $this->em->getRepository(Jobs::class)->findOneBy(['locale' => $locale, 'slug' => $slug, 'online' => true, 'validation' => true]); if($job === null) { throw $this->createNotFoundException('Page non trouvée'); } $othersJobs = null; if($job->getEnterprise() != null) { $othersJobs = $this->em->getRepository(Jobs::class)->findBy(['enterprise' => $job->getEnterprise(), 'online' => true]); } // Offres similaires basées sur catégorie, compétences, ville, titre $similarJobs = $this->em->getRepository(Jobs::class)->findSimilarJobs($job, 5); $count = 0; if($job->getViews() != null) { $count = $job->getViews() + 1; } $job->setViews($count); $this->em->persist($job); $this->em->flush(); return $this->render('application/whileresume/application/jobs/show.html.twig',[ 'slug' => $slug, 'job' => $job, 'othersJobs' => $othersJobs, 'similarJobs' => $similarJobs ]); } /** * Retourne les détails d'une offre en JSON pour la fiche modale (AJAX). * Si l'utilisateur n'est pas connecté, retourne uniquement les champs publics * (résumé + meta) avec un flag "locked" sur les détails. */ public function ajaxShow(Request $request, $slug): JsonResponse { $locale = $request->getLocale(); $user = $this->getUser(); $job = $this->em->getRepository(Jobs::class)->findOneBy([ 'locale' => $locale, 'slug' => $slug, 'online' => true, 'validation' => true ]); if ($job === null) { return new JsonResponse(['error' => 'not_found'], 404); } $isAuthenticated = $user !== null; $isCandidate = $isAuthenticated && $user->getCandidate() !== null; $enterpriseData = null; if ($job->getEnterprise() !== null) { $enterpriseData = [ 'id' => $job->getEnterprise()->getId(), 'slug' => $job->getEnterprise()->getSlug(), 'name' => $job->getEnterprise()->getCompanyName(), 'logo' => method_exists($job->getEnterprise(), 'getLogo') ? $job->getEnterprise()->getLogo() : null, 'city' => method_exists($job->getEnterprise(), 'getCity') ? $job->getEnterprise()->getCity() : null, 'country' => method_exists($job->getEnterprise(), 'getCountry') ? $job->getEnterprise()->getCountry() : null, ]; } // Données publiques (toujours visibles) $payload = [ 'id' => $job->getId(), 'slug' => $job->getSlug(), 'title' => $job->getJobTitle(), 'companyName' => $job->getCompanyName(), 'category' => $job->getCategory(), 'city' => $job->getCity(), 'country' => $job->getCountry(), 'employmentType' => $job->getEmploymentType(), 'remoteWork' => $job->getRemoteWork(), 'experienceLevel' => $job->getExperienceLevel(), 'salaryMin' => $job->getSalaryMin(), 'salaryMax' => $job->getSalaryMax(), 'salaryPeriod' => $job->getSalaryPeriod(), 'devise' => $job->getDevise(), 'jobSummary' => $job->getJobSummary(), 'verification' => $job->isVerification(), 'website' => method_exists($job, 'getWebsite') ? $job->getWebsite() : null, 'websearch' => method_exists($job, 'getWebsearch') ? $job->getWebsearch() : null, 'enterprise' => $enterpriseData, 'isAuthenticated' => $isAuthenticated, 'isCandidate' => $isCandidate, 'locked' => !$isAuthenticated, 'showUrl' => $this->generateUrl('locale_cvs_application_job_show', [ '_locale' => $locale, 'slug' => $slug ]), 'likeUrl' => null, ]; // Données détaillées (uniquement si connecté) if ($isAuthenticated) { $payload['keyResponsabilities'] = $job->getKeyResponsabilities(); $payload['requirements'] = $job->getRequirements(); $payload['benefits'] = $job->getBenefits(); if ($isCandidate) { $payload['likeUrl'] = $this->generateUrl('locale_cvs_application_job_like', [ '_locale' => $locale, 'slug' => $slug ]); } } return new JsonResponse($payload); } /** * API publique de recherche d'offres pour l'autocomplétion. * GET /api/jobs/search?q=...&locale=...&limit=... */ public function apiSearch(Request $request): JsonResponse { $query = trim((string) $request->query->get('q', '')); $locale = $request->query->get('locale', $request->getLocale()); $limit = max(1, min(20, (int) $request->query->get('limit', 6))); $offset = max(0, (int) $request->query->get('offset', 0)); if (mb_strlen($query) < 2) { return new JsonResponse([ 'items' => [], 'total' => 0, 'query' => $query, ]); } $repo = $this->em->getRepository(Jobs::class); $jobs = $repo->searchJobs($query, $locale, $offset, $limit); $total = $repo->countSearchJobs($query, $locale); $items = []; foreach ($jobs as $job) { $logo = null; if ($job->getEnterprise() !== null && method_exists($job->getEnterprise(), 'getLogo')) { $logo = $job->getEnterprise()->getLogo(); } $items[] = [ 'id' => $job->getId(), 'slug' => $job->getSlug(), 'title' => $job->getJobTitle(), 'companyName' => $job->getCompanyName(), 'category' => $job->getCategory(), 'city' => $job->getCity(), 'country' => $job->getCountry(), 'employmentType' => $job->getEmploymentType(), 'salaryMin' => $job->getSalaryMin(), 'salaryMax' => $job->getSalaryMax(), 'devise' => $job->getDevise(), 'logo' => $logo, 'url' => $this->generateUrl('locale_cvs_application_job_show', [ '_locale' => $locale, 'slug' => $job->getSlug(), ]), ]; } return new JsonResponse([ 'items' => $items, 'total' => $total, 'query' => $query, 'limit' => $limit, 'offset' => $offset, ]); } public function likeJob(Request $request, $slug): Response { $locale = $request->getLocale(); $user = $this->getUser(); if($user == null) { if($locale != "en") { return $this->redirectToRoute('locale_cvs_gestion_candidates_dashboard',['_locale' => $locale]); } return $this->redirectToRoute('cvs_gestion_candidates_dashboard'); } $candidate = $user->getCandidate(); $job = $this->em->getRepository(Jobs::class)->findOneBy(['slug' => $slug]); $jhl = $this->em->getRepository(JobsHasLikes::class)->findOneBy(['candidate' => $candidate, 'job' => $job]); if($jhl == null) { $jhl = new JobsHasLikes(); $jhl->setJob($job); $jhl->setCandidate($candidate); $jhl->setCreatedAt(new \DateTime("now")); $jhl->setUpdatedAt(new \DateTime("now")); $this->em->persist($jhl); $this->em->flush(); } if($locale != "en") { return $this->redirectToRoute('locale_cvs_gestion_candidates_dashboard',['_locale' => $locale]); } return $this->redirectToRoute('cvs_gestion_candidates_dashboard'); }}