<?php
namespace App\Controller;
use App\Entity\BlogArticle;
use App\Entity\Contract;
use App\Entity\ContractComment;
use App\Entity\ContractEstate;
use App\Entity\ContractPicture;
use App\Entity\ContractPromupInfo;
use App\Entity\Notification;
use App\Entity\Opinion;
use App\Entity\RefTown;
use App\Entity\Sponsorship;
use App\Entity\User;
use App\Service\AntiSpamService;
use App\Service\EmailService;
use App\Service\GeolocService;
use App\Service\PdfService;
use Sensio\Bundle\FrameworkExtraBundle\Configuration as FE;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
use Symfony\Component\Routing\Annotation\Route;
use App\Form\Type as FormType;
class DefaultController extends AbstractBaseController
{
/**
* @Route("/_navbar", name="navbar")
* @FE\Template()
*
* @param RequestStack $oRequestStack
*
* @return array
*/
public function _navbar(RequestStack $oRequestStack): array
{
return [
'request_attributes' => $oRequestStack->getMainRequest()->attributes,
];
}
/**
* @Route("/", name="homepage")
* @FE\Cache(public=true, smaxage=60)
*
* @return Response
*/
public function homepage(): Response
{
return $this->cacheResponse($this->render('default/homepage.html.twig', [
'form_search' => null,
'form_contract' => $this->createForm(FormType\ContractEstateSearchType::class)->createView(),
'contracts' => $this->getDoctrineRepository(Contract::class)->findBy(['status' => Contract::STATUS_ACCEPTED, 'isDiffusion' => true], ['id' => 'DESC'], 8),
'opinions' => $this->getDoctrineRepository(Opinion::class)->findByCriterias(),
]));
}
/**
* @Route("/agence", name="agency")
* @FE\Cache(public=true, smaxage=600)
*
* @return Response|array
*/
public function agency()
{
return $this->cacheResponse($this->render('default/agency.html.twig'));
}
/**
* @Route("/pack-multi-diffusion", name="pack")
* @FE\Cache(public=true, smaxage=600)
*
* @return Response|array
*/
public function pack()
{
return $this->cacheResponse($this->render('default/pack.html.twig'));
}
/**
* @Route("/nous-rejoindre", name="join_us")
* @FE\Template()
*
* @param Request $oRequest
* @param EmailService $oEmailSrv
* @param AntiSpamService $oAntispamServ
*
* @return Response|array
*/
public function joinUs(Request $oRequest, EmailService $oEmailSrv, AntiSpamService $oAntispamServ)
{
$oContract = null;
$aFormData = [];
$oForm = $this->createForm(FormType\JoinUsType::class, $aFormData);
$oForm->handleRequest($oRequest);
if ($oForm->isSubmitted() && $oForm->isValid()) {
$bRecaptchaValid = $oAntispamServ->validate($oRequest->get('antispam_hash'), $oRequest->get('g-recaptcha-response'));
if ($bRecaptchaValid) {
$aFormData = $oForm->getData();
$oEmailSrv->sendContactEmail($aFormData, $oContract);
$this->addFlash('primary', 'Votre demande a bien été transmise. Vous serez recontacté dans les plus brefs délais.');
return $this->redirectToRoute('join_us');
}
else {
$this->addFlash('danger', 'La vérification Anti-Spam a échouée. Veuillez recommencer.');
}
}
return [
'form' => $oForm->createView(),
'antispam_info' => $oAntispamServ->generateRecaptcha(),
];
}
/**
* @Route("/blog", name="blog")
* @FE\Cache(public=true, smaxage=600)
*
* @return Response
*/
public function blog(): Response
{
return $this->redirectToRoute('homepage');
$aCriterias = $this->isGranted('ROLE_ADMIN') ? [] : ['status' => BlogArticle::STATUS_PUBLISHED];
return $this->cacheResponse($this->render('default/blog.html.twig',[
'articles' => $this->getDoctrineRepository(BlogArticle::class)->findBy($aCriterias, ['publishedAt' => 'DESC', 'id' => 'DESC'])
]));
}
/**
* @Route("/blog/{iArticleId}", name="blog_show",
* requirements={"iArticleId": "\d+"}
* )
* @FE\Cache(public=true, smaxage=600)
*
* @param int $iArticleId
*
* @return Response
*/
public function blogArticle(int $iArticleId): Response
{
$oBlogArticle = $this->getDoctrineRepository(BlogArticle::class)->find($iArticleId);
if (!$oBlogArticle instanceof BlogArticle
|| (!$this->isGranted('ROLE_ADMIN') && $oBlogArticle->getStatus() !== BlogArticle::STATUS_PUBLISHED)) {
return $this->redirectToRoute('blog');
}
return $this->cacheResponse($this->render('default/blog_article.html.twig',[
'article' => $oBlogArticle,
]));
}
/**
* @Route("/parrainage", name="sponsorship")
* @FE\Template()
*
* @param Request $oRequest
*
* @return Response|array
*/
public function sponsorship(Request $oRequest)
{
return $this->redirectToRoute('homepage');
$oSponsorship = new Sponsorship();
$oForm = $this->createForm(FormType\SponsorshipType::class, $oSponsorship);
$oForm->handleRequest($oRequest);
if ($oForm->isSubmitted() && $oForm->isValid()) {
$this->persistAndFlush($oSponsorship);
$this->addFlash('success', 'Votre demande a bien été prise en compte.');
return $this->redirectToRoute('sponsorship');
}
return [
'form' => $oForm->createView(),
];
}
/**
* @Route("/les-annonces", name="contracts")
* @FE\Template()
*
* @param Request $oRequest
*
* @return array
*/
public function contracts(Request $oRequest): array
{
$aParams = array_merge(
$oRequest->request->get('contract_estate_search', []),
$oRequest->request->get('contract_search', [])
);
if ($oRequest->query->has('last_search')) {
$aParams = $oRequest->getSession()->get(self::SESS_KEY_SEARCH_PARAMS, []);
}
return [
'form' => $this->createForm(FormType\ContractEstateSearchType::class, $aParams)->createView(),
];
}
/**
* @Route("/les-annonces/search", name="contracts_search")
* @FE\Template()
*
* @param Request $oRequest
* @param GeolocService $oGeolocServ
*
* @return Response|array
*/
public function _search(Request $oRequest, GeolocService $oGeolocServ)
{
$iPage = $oRequest->request->get('page', 1);
$aParams = $oRequest->request->all();
$aParams['isFront'] = true;
// Save query
$oRequest->getSession()->set(self::SESS_KEY_SEARCH_PARAMS, $aParams);
$oRefTown = null;
if (!empty($aParams['location']) && !empty($aParams['distance'])) {
$oRepoRT = $this->getDoctrineRepository(RefTown::class);
$aParts = explode (' - ', $aParams['location']);
if (count($aParts) == 2) {
$oRefTown = $oRepoRT->findBestMatchByCriterias($aParts[0], $aParts[1]);
}
if (!$oRefTown instanceof RefTown) {
$aRefTowns = $oRepoRT->findByCriterias(['magicSearch' => $aParams['location']]);
if ($aRefTowns) {
$oRefTown = $aRefTowns[0];
}
}
if ($oRefTown instanceof RefTown) {
$aSquareInfo = $oGeolocServ->getSquareLatLng($oRefTown->getLocLat(), $oRefTown->getLocLng(), preg_replace('/[a-z €²]*/', '', $aParams['distance']));
$aParams['locLat'] = implode(GeolocService::SEPARATOR, [$aSquareInfo['min_lat'], $aSquareInfo['max_lat']]);
$aParams['locLng'] = implode(GeolocService::SEPARATOR, [$aSquareInfo['min_lng'], $aSquareInfo['max_lng']]);
}
}
$sSearchEntity = $aParams['class'] ?? ContractEstate::class;
$oRepo = $this->getDoctrineRepository($sSearchEntity);
$iNbResults = $oRepo->countByCriterias($aParams);
$aResults = $oRepo->findByCriterias($aParams, self::NB_RESULTS_PER_PAGE, self::NB_RESULTS_PER_PAGE * ($iPage - 1));
return [
'page' => $iPage,
'nb_results_per_page' => self::NB_RESULTS_PER_PAGE,
'nb_results' => $iNbResults,
'results' => $aResults,
];
}
/**
* @Route("/annonce/{sRefNetty}", name="contract")
* @FE\Template()
*
* @param Request $oRequest
* @param GeolocService $oGeolocServ
* @param string $sRefNetty
*
* @return Response|array
*/
public function contract(Request $oRequest, GeolocService $oGeolocServ, string $sRefNetty)
{
$oContract = $this->getDoctrineRepository(Contract::class)->findOneBy(['refNetty' => $sRefNetty]);
if (!$oContract instanceof Contract || !$oContract->getPromupInfo() || !$oContract->isAccessAllowed($oRequest->get('hash', ''))) {
return $this->redirectToRoute('homepage');
}
$aRelContracts = [];
if (!empty($oContract->getLocLat()) && !empty($oContract->getLocLng())) {
$aSquareInfo = $oGeolocServ->getSquareLatLng($oContract->getLocLat(), $oContract->getLocLng(), 30);
$aParams = [
'isFront' => true,
'getRelated' => $oContract,
'locLat' => implode(GeolocService::SEPARATOR, [$aSquareInfo['min_lat'], $aSquareInfo['max_lat']]),
'locLng' => implode(GeolocService::SEPARATOR, [$aSquareInfo['min_lng'], $aSquareInfo['max_lng']]),
];
$aRelContracts = $this->getDoctrineRepository(get_class($oContract))->findByCriterias($aParams, 16);
}
$oRefTown = null;
if ($oContract->getAddress() && $oContract->getAddress()->getPostalCode()) {
$oRefTown = $this->getDoctrineRepository(RefTown::class)->findBestMatchByCriterias($oContract->getAddress()->getPostalCode(), $oContract->getAddress()->getCity());
}
$oContract->setNbViews($oContract->getNbViews() + 1);
$this->persistAndFlush($oContract);
return [
'contract' => $oContract,
'related_contracts' => $aRelContracts,
'ref_town' => $oRefTown,
];
}
/**
* @Route("/annonce/{sRefNetty}/flyer-a4/{sOption}", name="contract_flyer_a4")
* @FE\Template()
*
* @param Request $oRequest
* @param PdfService $oPdfSrv
* @param string $sRefNetty
* @param string|null $sOption
*
* @return Response|array
*/
public function contractFlyerA4(Request $oRequest, PdfService $oPdfSrv, string $sRefNetty, string $sOption = null)
{
return $this->contractFlyerA5($oRequest, $oPdfSrv, $sRefNetty, $sOption);
/*$oContract = $this->getDoctrineRepository(Contract::class)->findOneBy(['refNetty' => $sRefNetty]);
if (!$oContract instanceof Contract || !$oContract->isAccessAllowed($oRequest->get('hash', ''))) {
return $this->json(['status' => 'NOK']);
}
$sFilename = $oPdfSrv->generateContractFlyerA4($oContract);
if ($sOption === 'view') {
return $this->render('partial/_viewer.html.twig', [
'path' => $sFilename,
'web_path' => $this->generateUrl('contract_flyer_a4', ['sRefNetty' => $sRefNetty]),
]);
}
return $this->file($sFilename);*/
}
/**
* @Route("/annonce/{sRefNetty}/flyer-a5/{sOption}", name="contract_flyer_a5")
* @FE\Cache(public=true, smaxage=600)
*
* @param Request $oRequest
* @param PdfService $oPdfSrv
* @param string $sRefNetty
* @param string|null $sOption
*
* @return Response|array
*/
public function contractFlyerA5(Request $oRequest, PdfService $oPdfSrv, string $sRefNetty, string $sOption = null)
{
$oContract = $this->getDoctrineRepository(Contract::class)->findOneBy(['refNetty' => $sRefNetty]);
if (!$oContract instanceof Contract
|| (!$oContract->isAccessAllowed($oRequest->get('hash', '')) && $oContract->getCustomer() !== $this->getSfUser())) {
return $this->json(['status' => 'NOK']);
}
$oSession = $oRequest->getSession();
$sFilename = $oSession->get('contractFlyerA5_' . $sRefNetty);
if (!$sFilename || !file_exists($sFilename) || $this->getSfUser()) {
$sFilename = $oPdfSrv->generateContractFlyerA5($oContract);
$oSession->set('contractFlyerA5_' . $sRefNetty, $sFilename);
}
if ($sOption === 'view') {
return $this->cacheResponse($this->render('partial/_viewer.html.twig',[
'path' => $sFilename,
'web_path' => $this->generateUrl('contract_flyer_a5', ['sRefNetty' => $sRefNetty]),
]));
}
return $this->file($sFilename);
}
/**
* @Route("/annonce/{sRefNetty}/dossier-vendeur/{sOption}", name="contract_bulk")
* @FE\Cache(public=true, smaxage=600)
*
* @param Request $oRequest
* @param PdfService $oPdfSrv
* @param string $sRefNetty
* @param string|null $sOption
*
* @return Response|array
*/
public function contractBulk(Request $oRequest, PdfService $oPdfSrv, string $sRefNetty, string $sOption = null)
{
$oContract = $this->getDoctrineRepository(Contract::class)->findOneBy(['refNetty' => $sRefNetty]);
if (!$oContract instanceof Contract
|| (!$oContract->isAccessAllowed($oRequest->get('hash', '')) && $oContract->getCustomer() !== $this->getSfUser())) {
return $this->json(['status' => 'NOK']);
}
$oSession = $oRequest->getSession();
$sFilename = $oSession->get('contractBulk_' . $sRefNetty);
if (!$sFilename || !file_exists($sFilename)) {
$sFilename = $oPdfSrv->generateContractBulk($oContract);
$oSession->set('contractBulk_' . $sRefNetty, $sFilename);
}
if ($sOption === 'view') {
return $this->cacheResponse($this->render('partial/_viewer.html.twig',[
'path' => $sFilename,
'web_path' => $this->generateUrl('contract_bulk', ['sRefNetty' => $sRefNetty]),
]));
}
return $this->file($sFilename);
}
/**
* @Route("/annonce/{sRefNetty}/liens-de-diffusion", name="contract_links")
* @FE\Cache(public=true, smaxage=600)
* @FE\Security("is_granted('ROLE_CUSTOMER')")
*
* @param Request $oRequest
* @param PdfService $oPdfSrv
* @param string $sRefNetty
* @param string|null $sOption
*
* @return Response|array
*/
public function contractLinks(Request $oRequest, PdfService $oPdfSrv, string $sRefNetty, string $sOption = null)
{
$oContract = $this->getDoctrineRepository(Contract::class)->findOneBy(['refNetty' => $sRefNetty]);
if (!$oContract instanceof Contract
|| (!$oContract->isAccessAllowed($oRequest->get('hash', '')) && $oContract->getCustomer() !== $this->getSfUser())) {
return $this->json(['status' => 'NOK']);
}
$sFilename = $oPdfSrv->generateContractLinks($oContract);
if ($sOption === 'view') {
return $this->cacheResponse($this->render('partial/_viewer.html.twig',[
'path' => $sFilename,
'web_path' => $this->generateUrl('contract_links', ['sRefNetty' => $sRefNetty]),
]));
}
return $this->file($sFilename);
}
/**
* @Route("/minisite/{sRefNetty}", name="contract_minisite")
* @FE\Template()
*
* @param Request $oRequest
* @param string $sRefNetty
*
* @return Response
*/
public function minisite(Request $oRequest, string $sRefNetty): Response
{
$sHash = $oRequest->get('hash', '');
return $this->redirect('https://www.avendre.site/annonce/'.$sRefNetty. ($sHash ? '?hash='. $sHash : ''));
}
/**
* @Route("/annonce/{iContractId}/picture/{iPictureId}", name="contract_picture",
* requirements={"iContractId": "\d+", "iPictureId": "\d+"}
* )
*
* @param Request $oRequest
* @param int $iContractId
* @param int $iPictureId
*
* @return Response
*/
public function contractPicture(Request $oRequest, int $iContractId, int $iPictureId): Response
{
$oPicture = $this->getDoctrineRepository(ContractPicture::class)->find($iPictureId);
if (!$oPicture instanceof ContractPicture || ($oPicture->getContract()->getId() !== $iContractId)) {
return $this->json(['status' => 'NOK']);
}
$sFilepath = $oPicture->getAbsolutePath(ContractPicture::CONF_TYPE[ContractPicture::PIC_TYPE_WPRO]);
if ($oPicture->getContract()->getIsCompromise()) {
$sFilepath = $oPicture->getAbsolutePath(ContractPicture::CONF_TYPE[ContractPicture::PIC_TYPE_WCOM]);
}
if (!file_exists($sFilepath)) {
$sFilepath = $oPicture->getAbsolutePath(ContractPicture::CONF_TYPE[ContractPicture::PIC_TYPE_PLE]);
}
if (!file_exists($sFilepath)) {
$sFilepath = realpath($this->getParameter('kernel.project_dir') . '/assets/images/fake_picture_1.jpg');
}
return $this->file($sFilepath, implode('_', [$oPicture->getContract()->getRefNetty(), $iPictureId]), ResponseHeaderBag::DISPOSITION_INLINE);
}
/**
* @Route("/faire-gerer", name="how_to_manage")
* @FE\Cache(public=true, smaxage=600)
* @FE\Template()
*
* @return Response|array
*/
public function howToManage()
{
return [];
}
/**
* @Route("/contact/{iContractId}", name="contact", requirements={"iContractId": "\d+"})
* @FE\Template()
*
* @param Request $oRequest
* @param EmailService $oEmailSrv
* @param AntiSpamService $oAntispamServ
* @param int|null $iContractId
*
* @return Response|array
*/
public function contact(Request $oRequest, EmailService $oEmailSrv, AntiSpamService $oAntispamServ, int $iContractId = null)
{
$oContract = null;
$aFormData = [];
if ($iContractId) {
$oContract = $this->getDoctrineRepository(Contract::class)->find($iContractId);
if ($oContract instanceof Contract) {
$aFormData = [
'reference' => $oContract->getRefNetty(),
'content' => 'Bonjour,
Nous souhaiterions plus d\'informations sur le bien '. $oContract->getRefNetty() .'.
Cordialement,',
];
}
}
$oForm = $this->createForm(FormType\ContactType::class, $aFormData);
$oForm->handleRequest($oRequest);
if ($oForm->isSubmitted() && $oForm->isValid()) {
$bRecaptchaValid = $oAntispamServ->validate($oRequest->get('antispam_hash'), $oRequest->get('g-recaptcha-response'));
if ($bRecaptchaValid) {
$oRobotUser = $this->getDoctrineRepository(User::class)->find(-1);
$aFormData = $oForm->getData();
$aFormData['content'] = 'Référence : ' . (strtoupper($aFormData['reference']) ?: '/' ) . PHP_EOL . $aFormData['content'];
if (!$oContract instanceof Contract) {
$iNb = preg_match_all('/(V[ATEMIFPG][0-9]+)/', $aFormData['content'], $aMatches);
if ($iNb === 1) {
$oContract = $this->getDoctrineRepository(Contract::class)->findOneBy(['refNetty' => $aMatches[0][0]]);
}
else {
$iNb = preg_match_all('/(P[0-9]{2}-[0-9]{4}-[0-9]+)/', $aFormData['content'], $aMatches);
if ($iNb === 1) {
$oContractPromupInfo = $this->getDoctrineRepository(ContractPromupInfo::class)->findOneBy(['reference' => $aMatches[0][0]]);
if ($oContractPromupInfo instanceof ContractPromupInfo) {
$oContract = $oContractPromupInfo->getContract();
}
}
}
}
if ($oContract instanceof Contract) {
$oCustomer = $oContract->getCustomer();
if ($oCustomer && $oCustomer->getUserCustomerService()) {
$oNotif = (new Notification())
->setGeneratedBy($oRobotUser)
->setGeneratedFor($oCustomer->getUserCustomerService())
->setSeverity(Notification::SEVERITY_IMPORTANT)
->setMessage(sprintf('Demande d\'information %s (%s)', $oContract->getRefNetty(), $aFormData['name']))
->setAction($this->generateUrl('bo_contract_overview', ['iContractId' => $oContract->getId()]))
;
$this->persistAndFlush($oNotif);
}
$sText = sprintf('%s (%s) %s', 'Demande d\'information', $aFormData['name'], PHP_EOL.$aFormData['content'].PHP_EOL.implode(' - ', [$aFormData['email'], $aFormData['phone']]));
$oContract->addComment($oRobotUser, $sText, ContractComment::CATEGORY_INFO);
$oContract->setNbDemands($oContract->getNbDemands() + 1);
$this->persistAndFlush($oContract);
} else {
$oEmailSrv->sendContactEmail($aFormData, $oContract);
}
$this->addFlash('primary', 'Votre demande a bien été transmise. Vous serez recontacté dans les plus brefs délais.');
return $this->redirectToRoute('contact');
}
else {
$this->addFlash('danger', 'La vérification Anti-Spam a échouée. Veuillez recommencer.');
}
}
return [
'form' => $oForm->createView(),
'antispam_info' => $oAntispamServ->generateRecaptcha(),
];
}
/**
* @Route("/mentions-legales", name="legal")
* @FE\Cache(public=true, smaxage=600)
*
* @return Response
*/
public function legal()
{
return $this->cacheResponse($this->render('default/legal.html.twig'));
}
/**
* @Route("/conditions-generales", name="cgu_cgv")
* @FE\Cache(public=true, smaxage=600)
*
* @return Response
*/
public function cgu_cgv()
{
return $this->cacheResponse($this->render('default/cgu_cgv.html.twig'));
}
}