<?php
declare(strict_types=1);
/**
* @author Mehrez Labidi
*/
namespace App\Controller;
use App\Helper\{
Utils,
ParametersProvider
};
use App\Services\Annonces\Elites\AbstractConstCapital as EliteConst;
use App\Services\Annonces\Elites\AbstractConstProfilsStrategiques as ProfilsConst;
use App\Services\MetaTag;
use App\Controller\EntityUsingController;
use Symfony\Component\HttpFoundation\{
Request,
RequestStack,
Response
};
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use App\Entity\{
RecherchesAvanceesElite,
DetailAnnonceCapitalImmateriel,
DetailAnnonceSyntheseStrategique,
Localisations
};
use App\Form\Type\Elite\RechercheAvanceeType;
use App\Services\Annonces\Elites\{
RechercheAvancee,
RechercheStandard
};
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use App\Services\ManagerEntity\DroitsAccesManagers;
use Symfony\Component\Form\Extension\Core\Type\{
TextareaType,
TextType,
EmailType,
HiddenType,
SubmitType
};
use Symfony\Component\Validator\Constraints\{
NotBlank
};
use App\Validator\Constraints\Emoji;
use Symfony\Component\Validator\Constraints as Assert;
use EWZ\Bundle\RecaptchaBundle\Form\Type\EWZRecaptchaType;
use App\Services\Mailer;
use App\Services\ManagerEntity\{
AnnoncesManagers,
ServicesPrestataireManagers
};
use App\Services\LogMarketingProvider;
use App\Services\Annonces\Elites\RechercheElite;
/**
* Description of EliteController
*
* @author mehrez
*/
class EliteController extends EntityUsingController {
public const MAX_AGE = 43200; // 12heures
public function __construct(MetaTag $metaTag, RechercheAvanceeType $rechercheAvanceeType, RechercheAvancee $rechercheAvancee, RechercheStandard $rechercheStandard, DroitsAccesManagers $dam, ParameterBagInterface $params, Mailer $mailer, AnnoncesManagers $am, ServicesPrestataireManagers $spm, LogMarketingProvider $lmp) {
$this->metaTag = $metaTag;
$this->rechercheAvancee = $rechercheAvancee;
$this->rechercheAvanceeType = $rechercheAvanceeType;
$this->rechercheStandard = $rechercheStandard;
$this->dam = $dam;
$this->mailer = $mailer;
$this->am = $am;
$this->spm = $spm;
$this->dns_fusacq = $params->get('app.DNS')['FUSACQ'];
$this->lmp = $lmp;
}
public function presentationElite(Request $request, $codePays): Response {
$metaTag = $this->metaTag
->setTitle("FUSACQ Elite : l’offre premium pour les repreneurs d’entreprise exigeants")
->setDescription("FUSACQ Elite : analyse stratégique, matching avancé, capital immatériel… L’offre idéale pour les repreneurs exigeants.");
$nb = $this->getDoctrine()
->getRepository(DetailAnnonceSyntheseStrategique::class)
->getNbTotal(); // nb total synthese generé validé envoyé
$criteres = [
"positionnement" => array_filter(EliteConst::criteresPositionnement()),
"clientele" => array_filter(EliteConst::criteresClientele()),
"potentiel" => array_filter(EliteConst::criteresPotentiel())
];
$stats = $this->getDoctrine()->getRepository(DetailAnnonceCapitalImmateriel::class)->getCapitalImmaterielStats();
foreach ($criteres as $key => $value) {
foreach ($value as $k => $v) {
if (in_array($k, array_keys($stats))) {
if ($stats[$k] == 0) { // ce cas est peu interessant
continue; // ce cas est peu interessant
}
$v = $v . " (" . $stats[$k] . ")";
}
$value[$k] = $v;
}
$criteres[$key] = $value;
}
$nbSyntheses = ($nb > 0) ? str_split((string) $nb) : NULL;
$lienAnnonce = '#';
$synthese = $this->getDoctrine()
->getRepository(DetailAnnonceSyntheseStrategique::class)
->getDerniereAnnonceSyntheseGratuitAujourdhui(); // list synthese generé validé envoyé access gratuit
$idAnnonce = (!empty($synthese)) ? $synthese['id_annonce'] : NULL;
if ($idAnnonce) {
$annonce = $this->am->getAnnonceVendeurArrayByIdAnnonce($idAnnonce);
if (!$annonce) {
throw $this->createNotFoundException('No annonce found for id ' . $idAnnonce);
}
$lienAnnonce = $this->generateUrl('reprendre_entreprise_details_annonce_vendeur', [
'slug' => Utils::slugify($annonce['titre_annonce']),
'nomLocalisation' => $annonce['nom_localisation_slug'],
'idAnnonce' => $idAnnonce,
'codePays' => $codePays
]);
}
$response = $this->render('elite/presentation_elite.html.twig', [
"metaTag" => $metaTag,
"criteres" => $criteres,
"lienAccesAnalyseGratuit" => $lienAnnonce,
"nbSyntheses" => $nbSyntheses
]);
$response->setPublic();
$response->setMaxAge(self::MAX_AGE); // 12heures
return $response;
}
public function editRechercheAvancee(Request $request, $codePays): Response {
$authentified = ($this->getUser()) ? true : false;
$accesElite = false;
if ($authentified) {
$accesElite = $this->dam->checkIfThisUserHasDroitService($this->getUser(), RechercheElite::CODE_SERVICE); // ELITE
}
$form = $this->createForm(RechercheAvanceeType::class, NULL, [
'method' => 'GET',
'csrf_protection' => false
]);
$form->handleRequest($request);
if ($form->isSubmitted()) {
$data = $request->query->all();
$criteres = array_filter(explode(",", $data['criteres']));
if (count($criteres) < RechercheAvancee::NB_MIN_CRITERES) {
$this->get('session')->getFlashBag()->clear(); // Clear tous les flashbags
$this->addFlash('error_recherche_elite', "Les critères ELITE sont obligatoires pour la recherche");
return $this->redirectToRoute('elite_recherche_avancee', ["codePays" => $codePays]);
}
$queryParams = array_filter($data, fn($item) => $item);
$queryParams['codePays'] = $codePays;
return $this->redirectToRoute('elite_list_recherche_avancee', $queryParams);
}
$metaTag = $this->metaTag
->setTitle("Recherche avancée Annonces - Reprendre ou développer une entreprise | Fusacq")
->setDescription("Affinez votre recherche d'annonces pour reprendre ou développer une entreprise : sélection par localisation, secteur, situation financière, profil de repreneur et critères ELITE.");
$criteres = EliteConst::getAllCriteres();
$recherches_sauvegardees = $this->getDoctrine()->getRepository(RecherchesAvanceesElite::class)->getRecherchesAvanceesEliteByIdUtilisateur();
$response = $this->render('elite/recherche_avancee.html.twig', [
"metaTag" => $metaTag,
"recherches_sauvegardees" => $recherches_sauvegardees,
"criteres" => $criteres,
"authentified" => $authentified,
"accesElite" => $accesElite,
"form" => $form->createView()
]);
$response->setPublic();
$response->setMaxAge(self::MAX_AGE); // 12heures
return $response;
}
public function rechercheAvancee(Request $request, $codePays): Response {
$authentified = ($this->getUser()) ? true : false;
$accesElite = false;
if ($authentified) {
$accesElite = $this->dam->checkIfThisUserHasDroitService($this->getUser(), RechercheElite::CODE_SERVICE); // ELITE
}
$form = $this->createForm(RechercheAvanceeType::class, NULL, [
'method' => 'GET',
'csrf_protection' => false
]);
$metaTag = $this->metaTag
->setTitle("Recherche avancée Annonces - Reprendre ou développer une entreprise | Fusacq")
->setDescription("Affinez votre recherche d'annonces pour reprendre ou développer une entreprise : sélection par localisation, secteur, situation financière, profil de repreneur et critères ELITE.");
$criteres = EliteConst::getAllCriteres();
$recherches_sauvegardees = $this->getDoctrine()->getRepository(RecherchesAvanceesElite::class)->getRecherchesAvanceesEliteByIdUtilisateur();
$response = $this->render('elite/recherche_avancee.html.twig', [
"metaTag" => $metaTag,
"recherches_sauvegardees" => $recherches_sauvegardees,
"criteres" => $criteres,
"authentified" => $authentified,
"accesElite" => $accesElite,
"form" => $form->createView()
]);
$response->setPublic();
$response->setMaxAge(self::MAX_AGE); // 12heures
$form->handleRequest($request);
if ($form->isSubmitted()) {
$data = $request->query->all();
if (!empty($data['from'])) {// recherche depuis le compte ou mail alerte // juste le formulaire rempli à afficher !!
return $response;
}
$criteres = array_filter(explode(",", $data['criteres']));
if (count($criteres) < RechercheAvancee::NB_MIN_CRITERES) {
$this->get('session')->getFlashBag()->clear(); // Clear tous les flashbags
$this->addFlash('error_recherche_elite', "Les critères ELITE sont obligatoires pour la recherche");
return $this->redirectToRoute('elite_recherche_avancee', ["codePays" => $codePays]);
}
$queryParams = array_filter($data, fn($item) => $item);
$queryParams['codePays'] = $codePays;
return $this->redirectToRoute('elite_list_recherche_avancee', $queryParams);
}
return $response;
}
public function listRechercheStandard(Request $request, $codePays): Response {
ini_set('memory_limit', '256M');
$this->denyAccessUnlessGranted('ROLE_USER'); // page inaccessible sans authentification
$acces = $this->dam->checkIfThisUserHasDroitService($this->getUser(), RechercheElite::CODE_SERVICE); // ELITE
if (!$acces) {
return $this->redirectToRoute('index', ['codePays' => Utils::codePaysWithoutDash($codePays)]);
}
$elite = $this->dam->checkIfThisUserHasDroitService($this->getUser(), [RechercheElite::CODE_SERVICE_ELITE]); // on loggue par defaut ELITE
$userIdentity = $this->getUser();
if ($elite) {
$this->lmp->ajouterActionLogsActions($userIdentity->_get('id_utilisateur'), RechercheElite::ID_LOG_ACTION_STANDARD, $userIdentity->_get('type_utilisateur'), "----"); // 81 // elite
} else {
$eliteEssai = $this->dam->checkIfThisUserHasDroitService($this->getUser(), [RechercheElite::CODE_SERVICE_ELITE_ESSAI]);
if ($eliteEssai) {
$this->lmp->ajouterActionLogsActions($userIdentity->_get('id_utilisateur'), RechercheElite::ID_LOG_ACTION_STANDARD_ESSAI, $userIdentity->_get('type_utilisateur'), "----"); //82 // elite essai
}
}
$metaTag = $this->metaTag
->setTitle("Recherche standard Annonces - Reprendre ou développer une entreprise | Fusacq")
->setDescription("Affinez votre recherche d'annonces pour reprendre ou développer une entreprise : sélection par localisation, secteur, situation financière et profil d’entreprise.");
$filtres = $request->query->all();
if (empty($filtres['identifiant_profil']) && !empty($filtres)) {
$this->get('session')->getFlashBag()->clear(); // Clear tous les flashbags
$this->addFlash('error_recherche_elite_standard', "Merci de sélectionner un profil stratégique");
return $this->redirectToRoute('elite_list_recherche_standard', ["codePays" => $codePays]);
}
$filtres = Utils::filterArray($filtres);
$page = max(1, $request->query->getInt('page', 1));
$limit = RechercheElite::NB_ANNONCES;
$offset = ($page - 1) * $limit;
// Ajouter l'offset aux filtres seulement si nécessaire
if ($page > 1) {
$filtres['offset'] = $offset;
}
// Récupérer les annonces
$annonces = $this->rechercheStandard->getAnnoncesResult($filtres);
// Calculer le total avec limite maximale
$totalAnnonces = !empty($annonces) ? min((int) RechercheElite::NB_TOTAL_RESULT, (int) Utils::firstValInArray($annonces)["total_count"]) : 0;
// Calculer le nombre total de pages
$totalPages = $totalAnnonces > 0 ? ceil($totalAnnonces / $limit) : 0;
// Ajuster la page si elle dépasse le maximum
if ($page > $totalPages && $totalPages > 0) {
$page = $totalPages;
$offset = ($page - 1) * $limit;
// Note : il faudrait probablement relancer la requête avec le bon offset ici
}
$profils = ProfilsConst::listProfilsForm();
$pays = $this->rechercheAvanceeType::listPays();
$secteurs = $this->rechercheAvanceeType::getNomSecteurActivitieLevel1();
$params = ParametersProvider::serializeParams($filtres);
$response = $this->render('elite/list_recherche_standard.html.twig', [
"metaTag" => $metaTag,
"profils" => $profils,
"pays" => $pays,
"secteurs" => $secteurs,
"filtres" => $filtres,
"params" => $params,
"currentPage" => $page, // pagination
"totalPages" => $totalPages, // pagination
"totalAnnonces" => $totalAnnonces, // pagination
"annonces" => $annonces ?? [] // pagination
]);
$response->setPublic();
$response->setMaxAge(self::MAX_AGE); // 12heures
return $response;
}
public function formRechercheStandard(RequestStack $requestStack, $lang, $codePays): Response {
$request = $requestStack->getMainRequest(); // Récupère la requête principale
$currentRoute = $request->attributes->get('_route');
$routeParams = $request->attributes->get('_route_params');
$pays = $this->rechercheAvanceeType::listPays();
$secteurs = $this->rechercheAvanceeType::getNomSecteurActivitieLevel1();
$filtres = $request->query->all();
unset($filtres['_path']);
$filtres = Utils::filterArray($filtres); // si vide pas de pb
$response = $this->render('elite/form_recherche_standard.html.twig', [
"pays" => $pays,
"secteurs" => $secteurs,
"filtres" => $filtres,
'lang' => $lang,
'codePays' => $codePays,
'currentRoute' => $currentRoute,
'routeParams' => $routeParams,
]);
$response->setPublic();
$response->setMaxAge(self::MAX_AGE); // 12heures
return $response;
}
public function listRechercheAvancee(Request $request, $codePays): Response {
ini_set('memory_limit', '256M');
$this->denyAccessUnlessGranted('ROLE_USER'); // page inaccessible sans authentification
$acces = $this->dam->checkIfThisUserHasDroitService($this->getUser(), RechercheElite::CODE_SERVICE); // ELITE
if (!$acces) {
return $this->redirectToRoute('index', ['codePays' => Utils::codePaysWithoutDash($codePays)]);
}
$elite = $this->dam->checkIfThisUserHasDroitService($this->getUser(), [RechercheElite::CODE_SERVICE_ELITE]); // on loggue par defaut ELITE
$userIdentity = $this->getUser();
if ($elite) {
$this->lmp->ajouterActionLogsActions($userIdentity->_get('id_utilisateur'), RechercheElite::ID_LOG_ACTION_AVANCEE, $userIdentity->_get('type_utilisateur'), "----"); // 81 // elite
} else {
$eliteEssai = $this->dam->checkIfThisUserHasDroitService($this->getUser(), [RechercheElite::CODE_SERVICE_ELITE_ESSAI]);
if ($eliteEssai) {
$this->lmp->ajouterActionLogsActions($userIdentity->_get('id_utilisateur'), RechercheElite::ID_LOG_ACTION_AVANCEE_ESSAI, $userIdentity->_get('type_utilisateur'), "----"); //82 // elite essai
}
}
$filtres = $request->query->all();
$page = $request->query->getInt('page', 1);
$page = max(1, $page);
unset($filtres['page']);
unset($filtres['recherche']);
unset($filtres['alerte']);
$annonces = (!empty($filtres)) ? $this->rechercheAvancee->getAnnoncesResult($filtres) : [];
$limit = RechercheAvancee::NB_ANNONCES;
$offset = ($page - 1) * $limit;
// Récupérer le nombre total pour la pagination
$totalAnnonces = count($annonces);
$totalPages = ceil($totalAnnonces / $limit);
// Vérifier que la page demandée n'excède pas le nombre total de pages
if ($page > $totalPages && $totalPages > 0) {
$page = $totalPages;
$offset = ($page - 1) * $limit;
}
$annonces = array_slice($annonces,(int)$offset, (int)$limit);
$params = ParametersProvider::serializeParams($filtres);
$metaTag = $this->metaTag
->setTitle("Recherche avancée Annonces - Reprendre ou développer une entreprise | Fusacq")
->setDescription("Affinez votre recherche d'annonces pour reprendre ou développer une entreprise : sélection par localisation, secteur, situation financière, profil de repreneur et critères ELITE.");
$response = $this->render('elite/list_recherche_avancee.html.twig', [
'metaTag' => $metaTag,
"params" => $params,
'currentPage' => $page, // pagination
'totalPages' => $totalPages, // pagination
"totalAnnonces" => $totalAnnonces, // pagination
'annonces' => $annonces ?? [] // pagination
]);
$response->setPublic();
$response->setMaxAge(self::MAX_AGE); // 12heures
return $response;
}
/**
* Supprime une recherche avancée sauvegardée par l'utilisateur connecté
*
* Cette méthode permet de supprimer une recherche avancée Elite préalablement
* sauvegardée par l'utilisateur authentifié. La suppression n'est effectuée que
* si la recherche appartient bien à l'utilisateur connecté.
*
* @param Request $request L'objet Request de Symfony contenant les données de la requête HTTP
* @param int $id_recherche L'identifiant unique de la recherche à supprimer
* @param string $codePays Le code pays utilisé pour la redirection après suppression
*
* @return Response Redirection vers la page de recherche avancée Elite avec le code pays
*
* @throws AccessDeniedException Si l'utilisateur n'est pas authentifié (ROLE_USER requis)
*/
public function supprimerRecherche(Request $request, $id_recherche, $codePays): Response {
$this->denyAccessUnlessGranted('ROLE_USER'); // page inaccessible sans authentification
$acces = $this->dam->checkIfThisUserHasDroitService($this->getUser(), RechercheElite::CODE_SERVICE); // ELITE
if (!$acces) {
return $this->redirectToRoute('index', ['codePays' => Utils::codePaysWithoutDash($codePays)]);
}
$em = $this->getDoctrine()->getManager();
$recherche = $em->getRepository(RecherchesAvanceesElite::class)
->findOneBy(["id" => $id_recherche, "id_utilisateur" => $this->getUser()->getId()]);
if ($recherche) {
$em->remove($recherche);
$em->flush();
}
return $this->redirectToRoute('elite_recherche_avancee', ["codePays" => $codePays]);
}
public function partager(Request $request, $idAnnonce, $codePays): Response {
$form = $this->createFormBuilder(NULL, [
'action' => $this->generateUrl('elite_partager_recherche_avancee', ['codePays' => $codePays, 'idAnnonce' => $idAnnonce]),
'method' => 'POST',
'attr' => ['novalidate' => 'novalidate'],
])
->add('id_annonce', HiddenType::class)
->add('email_destinataire', EmailType::class, ["constraints" => [new NotBlank(["message" => "le champ email est obligatoire"]), new Assert\Email(["message" => "l'adresse mail saisie est invalide"])]])
->add('email_expediteur', EmailType::class, ["constraints" => [new NotBlank(["message" => "le champ email est obligatoire"]), new Assert\Email(["message" => "l'adresse mail saisie est invalide"])]])
->add('nom_prenom', TextType::class, ["constraints" => [new NotBlank(["message" => "le champ prenom est obligatoire"])]])
->add('commentaire', TextareaType::class, ["required" => false, "constraints" => [new Emoji()], "attr" => ["placeholder" => "", "autocomplete" => "off"]])
->add('submit', SubmitType::class, ['label' => 'envoyer', 'attr' => ['class' => 'button-rond']])
->add('recaptcha', EWZRecaptchaType::class, ['mapped' => false])
->getForm();
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$data = $form->getData();
$annonce = $this->am->getAnnonceVendeurArrayByIdAnnonce($idAnnonce);
$expertRandom = $this->spm->getAnnonceVendeurRandomByLocalisation(Utils::getLocalisationPlusPrecisPossible($annonce['id_pays'], $annonce['id_region']));
$lienAnnonce = $this->generateUrl('reprendre_entreprise_details_annonce_vendeur', [
'slug' => Utils::slugify($annonce['titre_annonce']),
'nomLocalisation' => $annonce['nom_localisation_slug'],
'idAnnonce' => $idAnnonce,
'codePays' => $codePays
]);
$nomRegion = '';
$localisationsFromDB = $this->getDoctrine()->getManager()->getRepository(Localisations::class)->getNomLocalisationById(Utils::getLocalisationPlusPrecisPossible($annonce['id_pays'], $annonce['id_region']));
if (2 == count($localisationsFromDB)) { // si localisation departement+localisation pays alors on combine les deux
$nomRegion = $localisationsFromDB[1]['nom_localisation'] . ', ' . $localisationsFromDB[0]['nom_localisation'];
}
if (1 == count($localisationsFromDB)) {
$nomRegion = $localisationsFromDB[0]['nom_localisation'];
}
$varTemplate = [
'commentaire' => $data["commentaire"] ?? NULL,
'nomRegion' => ($nomRegion) ? $nomRegion : '',
'nomPrenom' => $data["nom_prenom"] ?? NULL,
'emailExpediteur' => $data["email_expediteur"] ?? NULL,
'emailDestinataire' => $data["email_destinataire"] ?? NULL,
'annonce' => $annonce ?? [],
'expertRandom' => $expertRandom ?? [],
'lang' => "fr",
'typeAnnonce' => "V",
'lienAnnonce' => $lienAnnonce,
'dns_fusacq' => $this->dns_fusacq
];
$subject = "cette annonce sur Fusacq me semble intéressante";
$this->mailer->sendmail(
Mailer::$senderAdress['notification'], $data['email_destinataire'], null, null, $subject, null, null,
'mails/templates/template_suggestion_FUSACQ.html.twig', $varTemplate, null
);
$this->get('session')->getFlashBag()->clear(); // Clear tous les flashbags
$this->addFlash('success_partage_annonce_elite', "votre message a bien été envoyé");
$currentUri = $request->headers->get('referer');
return $this->redirect($currentUri);
}
$response = $this->render(
'elite/includes/partager.html.twig',
[
'codePays' => $codePays,
'form' => $form->createView(),
'idAnnonce' => $idAnnonce,
]
);
$response->setPublic();
$response->setMaxAge(self::MAX_AGE); // 12heures
return $response;
}
public function ongletAtoutLeviersNonAth(Request $request, $codePays): Response {
$lienAnnonce = '#';
$synthese = $this->getDoctrine()
->getRepository(DetailAnnonceSyntheseStrategique::class)
->getDerniereAnnonceSyntheseGratuitAujourdhui(); // list synthese generé validé envoyé access gratuit
$idAnnonce = (!empty($synthese)) ? $synthese['id_annonce'] : NULL;
if ($idAnnonce) {
$annonce = $this->am->getAnnonceVendeurArrayByIdAnnonce($idAnnonce);
if (!$annonce) {
throw $this->createNotFoundException('No annonce found for id ' . $idAnnonce);
}
$lienAnnonce = $this->generateUrl('reprendre_entreprise_details_annonce_vendeur', [
'slug' => Utils::slugify($annonce['titre_annonce']),
'nomLocalisation' => $annonce['nom_localisation_slug'],
'idAnnonce' => $idAnnonce,
'codePays' => $codePays
]);
}
$response = $this->render('reprendre_entreprise/fragments/detail_annonce_elite/onglet_atout_levier_non_auth.html.twig',
[
'controller_name' => 'EliteController',
'lienAnnonce' => $lienAnnonce,
'synthese'=>$synthese,
'codePays' => $codePays
]
);
$response->setPublic();
$response->setMaxAge(self::MAX_AGE); // 12heures
return $response;
}
}