<?php
namespace App\Controller;
use App\Elastica\ReviewSearch;
use App\Entity\Advantage;
use App\Entity\Advertisement;
use App\Entity\AdvertisementAdvantages;
use App\Entity\Files;
use App\Entity\RentalRecord;
use App\Entity\Subscription;
use App\Entity\Meeting;
use App\Entity\Review;
use App\Form\AdvertisementForm;
use App\Form\SearchAdvertisementForm;
use App\Service\GeocodingService;
use App\Service\FileUploader;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Finder\Exception\AccessDeniedException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Router;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Serializer\SerializerInterface;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Cocur\Slugify\SlugifyInterface;
use Symfony\Component\Translation\TranslatorInterface;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
class AdvertisementController extends AbstractController
{
private $slugify;
/**
* @var TranslatorInterface
*/
private $translator;
private $parameterBag;
public function __construct(ParameterBagInterface $parameterBag)
{
$this->parameterBag = $parameterBag;
}
/**
* Add/Edit advertisement
* @param Request $request
* @return Response
* @Route("/advertisement/edit/{id}", name="advertisement_edit")
*/
public function edit($id = 0,Request $request, FileUploader $uploader, SerializerInterface $serializer)
{
$em = $this->getDoctrine()->getManager();
$user = $this->getUser();
$role = $user->getRoles();
if (in_array('ROLE_PRO',$user->getRoles()) && $user->getAgency()==null ) {
$this->addFlash('error',"Compléter votre profil pour accéder à toutes les fonctionnalités du site!");
return $this->redirectToRoute('complete_profil');
}
if (in_array('ROLE_USER',$user->getRoles()) && $user->getUsername()=='' ) {
$this->addFlash('error',"Compléter votre profil pour accéder à toutes les fonctionnalités du site!");
return $this->redirectToRoute('user_account');
}
$advertisement = $id!=0 ? $em->getRepository('App\Entity\Advertisement')->find($id) : new Advertisement();
if($advertisement->getId()!=null){
if($advertisement->getUser()->getId()!= $user->getId()){
throw new NotFoundHttpException();
}
if($advertisement->getStatus()== Advertisement::STATUS_DEACTIVATED){
$this->addFlash('warning', 'Cette annonce a été retirée par son propriétaire!');
return $this->redirectToRoute('homepage');
}
if($advertisement->getStatus()== Advertisement::STATUS_REFUSED){
$this->addFlash('warning', 'Cette annonce a été supprimée');
return $this->redirectToRoute('homepage');
}
$advertisement->setPictures(null);
$advertisement->setDocuments(null);
}
if($advertisement->getAvailableDate()!=null){
$advertisement->setAvailableDate($advertisement->getAvailableDate()->format('d/m/Y'));
$advertisement->setNoDate(false);
}else{
$advertisement->setNoDate(true);
}
if($advertisement->getSublease()){
$advertisement->setSubleaseDuration($advertisement->getSubleaseDuration());
}
if($advertisement->getAdvantages()!=null){
$list_advantages = explode(',',$advertisement->getAdvantages());
$list = [];
foreach($list_advantages as $ad){
$advantage = $em->getRepository("App\Entity\Advantage")->findOneBy(['name'=>$ad]);
if($advantage!=null){
$list[]= $advantage;
}
}
$advertisement->setAdvantages($list);
}
$form = $this->createForm(AdvertisementForm::class, $advertisement, [
'role' => $role,
]);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$advert = $form->getData();
$advert->setImported(false);
$geocodingService = new GeocodingService($_ENV['GEOCODING_API_KEY'],$em);
$city = null;
try{
$city = $geocodingService->decodeAddress($advert->getAddress());
}catch(\Exception $ex){}
if($city==null){
$this->addFlash('warning', 'L\'adresse renseigné est incorrecte!');
}else{
$advert->setPostalCode($city->getPostalCode());
$advert->setCity($city->getCity());
$advert->setDepartment($city->getDepartment()->getShortName());
$advert->setRegion($city->getDepartment()->getRegion()->getLongName());
$advert->setLongitude(floatval($city->getLongitude()));
$advert->setLatitude(floatval($city->getLatitude()));
if($advert->getNoDate()==0){
if ( preg_match( '/((0[1-9]|[12]\d|3[01])\/(0[1-9]|1[0-2])\/[12]\d{3})/', $advert->getAvailableDate()) ) {
$availableDate = \DateTime::createFromFormat( 'd/m/Y', $advert->getAvailableDate() );
}else{
$availableDate = null;
}
$advert->setAvailableDate($availableDate);
}else{
$advert->setAvailableDate(null);
}
if($advert->getSublease() && $advert->getSubleaseDuration()>0){
$advert->setDuration($advert->getSubleaseDuration());
}
// Retrieve previously uploaded pictures and add them to advertisement
if (0 === count($advert->getPictures())) {
$uploadedPictures = json_decode($request->request->get('uploadedPictures'));
if ($uploadedPictures) {
foreach ($uploadedPictures as $fileId) {
$file = $em->getRepository(Files::class)->find($fileId);
if ($file) {
$advert->addFile($file);
}
}
}
}
if(is_array($advert->getAdvantages()) && sizeof($advert->getAdvantages())>0){
$list_advantages = [];
foreach($advert->getAdvantages() as $advantage){
$list_advantages[]=$advantage->getName();
}
$advert->setAdvantages(implode(',',$list_advantages));
}else if($advert->getAdvantages()==null){
$advert->setAdvantages(null);
}
if(is_null($advert->getNew())){
$advert->setNew(false);
}
$advert->setOwner(($advert->getOwner() !== null ? $advert->getOwner() : true));
$advert->setUser($user);
if($advert->getSale()==null){
$advert->setSale(false);
}
if($advert->getEnergyBalance()== null || !in_array(strtolower($advert->getEnergyBalance()),['a','b','c','d','e','f','g'])){
$advert->setEnergyBalance('unknown');
}
$message = 'Annonce modifiée!';
if($advert->getId()==null){
$advert->setStatus(Advertisement::STATUS_PUBLISHED);
$em->persist($advert);
$message = 'Annonce mise en ligne !';
}
$em->flush();
$this->addFlash('success',$message);
$slugify = $this->get('slugify');
$translator = $this->get('translator');
if (in_array('ROLE_PRO', $user->getRoles())) {
$advert_slug = $slugify->slugify($translator->transchoice('label.advertisement.title',$advert->getRoomNumber(), ['%category%'=>$translator->trans($advert->getCategory()),'%type%'=>$translator->trans($advert->getTypeLabel()), '%roomNumber%'=> $translator->trans($advert->getRoomNumber()), '%surface%'=>$translator->trans($advert->getSurface())]));
return $this->redirectToRoute('advertisement_show', ['id' => $advert->getId(),'slug'=>$advert_slug]);
}else{
return $this->redirectToRoute('advertisement_publish');
}
}
}
return $this->render('advertisement/new.html.twig', [
'advertisement' => $advertisement,
'form' => $form->createView(),
'uploadedPictures' => $this->saveUploadedPictures($request, $uploader)
]);
}
/**
* Show Advertisement
* @param Request $request
* @param Advertisement $advertisement
* @return Response
* @Route("/advertisement/show/{id}/{slug}", name="advertisement_show")
*/
public function show( Advertisement $advertisement,$slug,Request $request, SlugifyInterface $slugify,TranslatorInterface $translator, RouterInterface $router, ReviewSearch $reviewSearch = null)
{
if($advertisement->getStatus()== Advertisement::STATUS_DEACTIVATED){
$this->addFlash('warning', 'Cette annonce a été retirée par son propriétaire!');
return $this->redirectToRoute('homepage');
}
if($advertisement->getStatus()== Advertisement::STATUS_REFUSED){
$this->addFlash('warning', 'Cette annonce a été supprimée');
return $this->redirectToRoute('homepage');
}
$advert_slug = $slugify->slugify($translator->transchoice('label.advertisement.title',$advertisement->getRoomNumber(), ['%category%'=>$translator->trans($advertisement->getCategory()),'%type%'=>$translator->trans($advertisement->getTypeLabel()), '%roomNumber%'=> $translator->trans($advertisement->getRoomNumber()), '%surface%'=>$translator->trans($advertisement->getSurface())]));
if(strcasecmp($advert_slug,$slug)!=0){
throw new NotFoundHttpException();
}
$form = $this->createForm(SearchAdvertisementForm::class, null, [
'action' => $this->generateUrl('advertisement_search'),
'method' => 'GET',
]);
$form->handleRequest($request);
$baseUrl = $request->getSchemeAndHttpHost() . '/search';
$referer = $request->headers->get('referer');
if (substr(str_replace('https://', 'http://', $referer), 0, strlen($baseUrl)) === str_replace('https://', 'http://', $baseUrl)) {
$searchUrl = $referer;
} else {
$searchUrl = $router->generate('advertisement_search');
}
$creator_user = $advertisement->getUser()->getRoles();
$role_creator = $creator_user[0];
$em = $this->getDoctrine()->getManager();
$hasApplication = false;
if($this->getUser()!=null){
$result = $em->getRepository('App\Entity\RentalRecord')->getAdvertRentalByUser($advertisement,$this->getUser());
if(sizeof($result)>0){
$hasApplication = true;
}
}
$em = $this->getDoctrine()->getManager();
$qb = $em->getRepository('App\Entity\FluxRss')->createQueryBuilder('flux')
->addSelect("flux.id,flux.title,flux.link,flux.longitude,flux.latitude,flux.city,flux.department,flux.region,flux.postalCode,flux.pinColor")
->where('flux.department=:department')
->andWhere('flux.region=:region')
->andWhere('flux.city=:city OR flux.city is null')
->setParameter('city', $advertisement->getCity())
->setParameter('department', $advertisement->getDepartment())
->setParameter('region', $advertisement->getRegion())
->orderBy('flux.type', 'ASC');
$query = $qb->getQuery();
$result = $query->getResult();
$results =[
'city_name' => $advertisement->getCity(),
'data' => $result
];
$paramsTerm = [];
if($advertisement->getPostalCode()!='' && $advertisement->getPostalCode()!=null){
$paramsTerm['postalCode'] = $advertisement->getPostalCode();
}
if($advertisement->getCity()!='' && $advertisement->getCity()!=null){
$paramsTerm['city'] = $advertisement->getCity();
}
if($advertisement->getDepartment()!='' && $advertisement->getDepartment()!=null){
$paramsTerm['department'] = $advertisement->getDepartment();
}
if($advertisement->getRegion()!='' && $advertisement->getRegion()!=null){
$paramsTerm['region'] = $advertisement->getRegion();
}
$reviewResults = $reviewSearch->searchPaginated($paramsTerm,5,0);
$qb = $em->getRepository('App\Entity\Statistics')->createQueryBuilder('stat')
->addSelect("stat.nbPopulation,stat.density,stat.activePopulation,stat.averageIncome,stat.sqrtFtAveragePrice,stat.nbFamily")
->where('stat.department=:department')
->andWhere('stat.region=:region')
->andWhere('stat.city=:city')
->andWhere("stat.type='COM'")
->setParameter('city', $advertisement->getCity())
->setParameter('department', $advertisement->getDepartment())
->setParameter('region', $advertisement->getRegion())
->orderBy('stat.type', 'ASC')
->setMaxResults(1);
$query = $qb->getQuery();
$result = $query->getResult();
$stat = null;
if(sizeof($result)>0){
$stat = $query->getResult()[0];
}
return $this->render('advertisement/show.html.twig', [
'form' => $form->createView(),
'advertisement' => $advertisement,
'reviews' => $reviewResults,
'role' => $role_creator,
'searchUrl' => $searchUrl,
'hasApplication' => $hasApplication,
'rssData' => $results,
'stat' => $stat
]);
}
/**
* Show Advertisement
* @param Request $request
* @param Advertisement $advertisement
* @return Response
* @Route("/advertisement/details/{id}/{slug}", name="advertisement_details")
*/
public function details(Request $request, Advertisement $advertisement, Router $router)
{
$user = $this->getUser();
if($user->getId() != $advertisement->getUser()->getId()){
throw new NotFoundHttpException();
}
if($advertisement->getStatus()== Advertisement::STATUS_REFUSED){
$this->addFlash('warning', 'Cette annonce a été supprimée');
return $this->redirectToRoute('homepage');
}
$em = $this->getDoctrine()->getManager();
$rentalRecords = $em->getRepository('App\Entity\RentalRecord')->getAdvertRentalByStatus($advertisement->getId(), RentalRecord::STATUS_ACTIVATE);
return $this->render('advertisement/details.html.twig', [
'advertisement' => $advertisement,
'rentalRecords' => $rentalRecords
]);
}
/**
* upload document view for ad moderation
* @param Advertisement $advertisement
* @return JsonResponse
* @Route("/advertisement/upload/upload_view/{id}", name="address_proof_view")
*/
public function documentUploadView(Advertisement $advertisement)
{
return new JsonResponse(['error' => false, 'view' => $this->renderView(':user:modal_edit_advertisement.html.twig', ['advertisement' => $advertisement])]);
}
/**
* Edit advert image view
* @param Advertisement $advertisement
* @return JsonResponse
* @Route("/advertisement/image/edit_view/{id}", name="advertisement_image_edit_view")
*/
public function imageEditView(Advertisement $advertisement)
{
return new JsonResponse(['error' => false, 'view' => $this->renderView(':user:modal_advert_image.html.twig', ['advertisement' => $advertisement])]);
}
/**
* Advertisement published
* @return Response
* @Route("/advertisement/publish", name="advertisement_publish")
*/
public function publishedMessageAction()
{
return $this->render('advertisement/finish.html.twig',[]);
}
/**
* Adding image
*
* @param Advertisement $advertisement
* @param Request $request
* @param FileUploader $uploader
* @return JsonResponse
* @Route("/advertisement/image/upload/{id}", name="advertisement_image_upload")
*/
public function addPicture(Advertisement $advertisement,Request $request, FileUploader $uploader)
{
if ($request->isMethod(Request::METHOD_POST)) {
$picture = $request->files->get('picture');
if ($picture instanceof UploadedFile) {
$imageName = $uploader->uploadImage($picture);
$file = new Files();
$file->setPath($imageName);
$file->setName($picture->getClientOriginalName());
$file->setSize($picture->getClientSize());
$em = $this->getDoctrine()->getManager();
$em->persist($file);
$em->flush();
$advertisement->addFile($file);
try{
$em->flush();
}
catch(\Exception $ex){}
return new JsonResponse(['error' => false,'link'=>$this->generateUrl('advertisement_image_remove',['id'=>$advertisement->getId(),'file'=>$file->getId()])]);
}
}
return new JsonResponse(['error' => true, "message" => 'Image non enregistrée']);
}
/**
* Remove image
* @param Advertisement $advertisement
* @param Files $file
* @param Request $request
* @return JsonResponse
* @Route("/advertisement/image/remove/{id}/{file}", name="advertisement_image_remove")
*/
public function removePicture(Advertisement $advertisement,Files $file,Request $request)
{
if ($request->isMethod(Request::METHOD_POST)) {
$em = $this->getDoctrine()->getManager();
$advertisement->removeFile($file);
$em->flush();
return new JsonResponse(['error' => false]);
}
return new JsonResponse(['error' => true, "message" => 'Image non supprimée']);
}
/**
* upload document for ad moderation
* @param Request $request
* @param Advertisement $advertisement
* @param FileUploader $uploader
* @return Response
* @Route("/advertisement/upload/document/{id}", name="address_proof")
*/
public function documentUpload(Request $request, Advertisement $advertisement, FileUploader $uploader)
{
$current_user = $this->getUser();
$ad_creator = $advertisement->getUser();
if ($current_user == $ad_creator) {
$document = $request->files->get('upload_documents');
if ($document instanceof UploadedFile && in_array($document->getMimeType(), ['application/pdf', 'application/x-pdf'])) {
$fileName = $uploader->uploadFile($document);
$advertisement->setDocuments($fileName);
$em = $this->getDoctrine()->getManager();
$em->persist($advertisement);
$em->flush();
$this->addFlash('success', 'Information mis à jour!');
}else{
$this->addFlash('error', 'Extension du fichier invalide!');
}
return $this->redirectToRoute('user_account', ['tab' => 'advertisements']);
}
throw new \Exception('Cette page ne vous est pas accessible');
}
/**
* Disable an advertisement
* @param Advertisement $advertisement
* @return JsonResponse
* @Route("/advertisement/disable/{id}", name="disable_advertisement")
*/
public function disable(Advertisement $advertisement)
{
$error = true;
$user = $this->getUser();
if ($user->getId() !== $advertisement->getUser()->getId()) {
$message = "Opération non autorisée!";
} else {
$em = $this->getDoctrine()->getManager();
$advertisement->setStatus(Advertisement::STATUS_DEACTIVATED);
$em->flush();
$message = "Annonce désactivée avec succès!";
$error = false;
}
return new JsonResponse(['error' => $error, "message" => $message]);
}
/**
* Enable an advertisement
* @param Advertisement $advertisement
* @return Response
* @Route("/advertisement/enable/{id}", name="enable_advertisement", methods={"POST"})
*/
public function enable(Advertisement $advertisement)
{
$message = "Impossible de réactiver cette annonce!";
$error = true;
$user = $this->getUser();
if ($user->getId() !== $advertisement->getUser()->getId()) {
$message = "Opération non autorisée!";
} else {
$em = $this->getDoctrine()->getManager();
$advertisement->setStatus(Advertisement::STATUS_PUBLISHED);
$em->flush();
$message = "Annonce réactivée avec succès!";
$error = false;
}
return new JsonResponse(['error' => $error, "message" => $message]);
}
/**
* Bookmark an advertisement
* @param Request $request
* @param Advertisement $advertisement
* @return Response
* @Route("/advertisement/{id}/show/bookmark", name="bookmark")
*/
public function bookmark(Request $request, Advertisement $advertisement)
{
$user = $this->getUser();
$id_ad = $advertisement->getId();
$em = $this->getDoctrine()->getManager();
if (false === $user->hasBookmark($advertisement)) {
$user->addBookmarks($advertisement);
$em->flush();
$this->addFlash('success', 'Annonce ajoutée aux favoris !');
} else {
$user->removeBookmarks($advertisement);
$em->flush();
$this->addFlash('success', 'Annonce retirée aux favoris !');
}
return $this->redirectToRoute('advertisement_show', ['id' => $id_ad]);
}
/**
* Save meeting
* @param Request $request
* @param Advertisement $advertisement
* @return Response
* @Route("/advertisement/meeting/add/{id}", name="save_meeting")
*/
public function saveMeeting(Request $request, Advertisement $advertisement)
{
$user = $this->getUser();
$em = $this->getDoctrine()->getManager();
$meeting = new Meeting();
$meeting->setCreatedAt(new \DateTime());
$meeting->setUser($user);
$meeting->setEmail($request->get('email'));
$meeting->setPhone($request->get('phone'));
$meeting->setName($request->get('name'));
$meeting->setAdvertisement($advertisement);
$meeting->setSeen(false);
$em->persist($meeting);
$em->flush();
return new JsonResponse([]);
}
/**
* Remove meeting
* @param Advertisement $advertisement
* @param RentalRecord $rental
* @param Request $request
* @Route("/advertisement/meeting/remove/{id}/", name="remove_meeting")
*/
public function removeMeeting(Meeting $meeting,Request $request)
{
if ($request->isMethod(Request::METHOD_POST)) {
$em = $this->getDoctrine()->getManager();
$user = $this->getUser();
if($user->getId() == $meeting->getAdvertisement()->getUser()->getId()){
$meeting->setSeen(true);
$em->flush();
}
return new JsonResponse(['error' => false]);
}
return new JsonResponse(['error' => true, "message" => 'Demande non supprimée']);
}
/**
* Remove rental records
* @param Advertisement $advertisement
* @param RentalRecord $rental
* @param Request $request
* @Route("/advertisement/rental/remove/{id}/{rental}", name="advertisement_rental_remove")
*/
public function removeRental(Advertisement $advertisement,RentalRecord $rental,Request $request)
{
if ($request->isMethod(Request::METHOD_POST)) {
$em = $this->getDoctrine()->getManager();
if($advertisement->getId() == $rental->getAdvertisement()->getId()){
$rental->setStatus(RentalRecord::STATUS_DECLINE);
$em->flush();
return new JsonResponse(['error' => false]);
}
}
return new JsonResponse(['error' => true, "message" => 'Candidature non supprimée']);
}
/**
* If pictures have been sent in form, upload and save them
* Like this, if the form fails, the pictures will still be added on second submit
*
* @param Request $request
* @param FileUploader $uploader
* @return string
*/
private function saveUploadedPictures(Request $request, FileUploader $uploader)
{
$uploadedPictures = [];
if ($request->isMethod(Request::METHOD_POST)) {
$pictures = $request->files->get('advertisement_form')['pictures'];
if ($pictures) {
foreach ($pictures as $image) {
if ($image instanceof UploadedFile) {
$imageName = $uploader->uploadImage($image);
$file = new Files();
$file->setPath($imageName);
$file->setName($image->getClientOriginalName());
if (!$image->isFile()) {
continue;
}
$file->setSize($image->getClientSize());
$em = $this->getDoctrine()->getManager();
$em->persist($file);
$em->flush();
$uploadedPictures[] = $file->getId();
}
}
}
}
if (!sizeof($uploadedPictures) && $request->request->get('uploadedPictures') !== '') {
$uploadedPictures = json_decode($request->request->get('uploadedPictures'));
}
return json_encode($uploadedPictures);
}
}