<?php
namespace App\Controller;
use App\Entity\Dvf;
use App\Entity\Ville;
use App\Repository\PmcVilleRepository;
use App\Repository\VilleRepository;
use App\Services\ApiData;
use Doctrine\ORM\EntityManagerInterface;
use http\Exception\UnexpectedValueException;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Serializer;
use Doctrine\Common\Annotations\AnnotationReader;
use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader;
class PmcController extends AbstractController
{
private $entityManager;
private $request;
const GROUP_API = 'pmc:api';
private $errors = [];
public function __construct(EntityManagerInterface $entityManager, RequestStack $requestStack)
{
$this->entityManager = $entityManager;
$this->request = $requestStack->getCurrentRequest();
}
protected function returnJsonResponseApi($groups, $datas)
{
$classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
$normalizer = new ObjectNormalizer($classMetadataFactory);
$serializer = new Serializer([$normalizer]);
$datasSerialized = $serializer->normalize($datas, null, ['groups' => $groups]);
return new JsonResponse($datasSerialized);
}
/**
* @Route("/api/pmc", name="pmc")
* @throws \Symfony\Component\Serializer\Exception\ExceptionInterface
*/
public function index(ApiData $apiData)
{
$ville = $this->validVille();
if(count($this->errors)) {
$datas = $this->errors;
}else {
$datas = $apiData->getDatas($ville);
$datas = array_merge($datas, [
'ville' => $ville,
'insee' => json_decode($ville->getInsee(),true)
]);
}
return $this->returnJsonResponseApi(self::GROUP_API, $datas);
}
/**
* @Route("/api/pmc/ville-replace", name="pmc_replace")
* @throws \Symfony\Component\Serializer\Exception\ExceptionInterface
*/
public function villeReplace(ApiData $apiData, PmcVilleRepository $pmcVilleRepository)
{
$ville = $this->validVille();
$this->validType();
$this->validOffre();
if(count($this->errors)) {
$datas = $this->errors;
}else{
$pmcVille = $pmcVilleRepository->getVilleReplace(
$ville,
$this->request->query->get('type'),
$this->request->query->get('offre') === 'location'
);
$datas = $apiData->getDatas($pmcVille->getVille());
$datas['villeReplaced'] = $ville;
$datas['ville'] = $pmcVille->getVille();
}
return $this->returnJsonResponseApi(self::GROUP_API, $datas);
}
/**
* @Route("/api/pmc/arround-city", name="pmc_arround_city")
* @throws \Symfony\Component\Serializer\Exception\ExceptionInterface
*/
public function cityArround(ApiData $apiData)
{
$ville = $this->validVille();
$this->validType();
$this->validOffre();
$this->validYear();
if(count($this->errors)) {
$datas = $this->errors;
}else{
$datas = $apiData->arroundCityPmcData(
$ville,
$this->request->query->get('type'),
$this->request->query->get('offre'),
$this->request->query->get('year'),
$this->request->query->get('pondere') == '1'
);
}
return $this->returnJsonResponseApi(self::GROUP_API, $datas);
}
/**
* @Route("/api/pmc/insert-dvf", name="dvf_insert")
* @throws \Symfony\Component\Serializer\Exception\ExceptionInterface
*/
public function insertDvf(Request $request)
{
$post = $request->request->all();
$get = $request->query->all();
$datas = !empty($post) ? $post : $get;
$year = $datas['year'] /* année : 2021 */;
$idbien = $datas['id_bien'];
$natureMutation = $datas['type_offre']/* typeOffre : Location, Vente */;
$valeurFonciere = $datas['valeur_fonciere'];/* float accepté */
$codePostal = $datas['ville_cp'];
$nomCommune = $datas['nom_commune'];/* avec majuscules */
$codeInsee = $datas['code_insee'];
$codeDpt = $datas['code_departement'];/* 34 pour hérault */
$typeBien = $datas['type_bien'];/* maison, appartement */
$nbPieces = $datas['nb_pieces'];
$surface = $datas['surface'];
$latitude = $datas['latitude'];/* float */
$longitude = $datas['longitude'];/* float */
$codeTypeLocal = $datas['code_type_bien'];/* 1 = maison, 2 = appartement */
$dvf = (new Dvf())
->setIdMutation($year . '-' . $idbien)
->setNatureMutation($natureMutation)
->setDateMutation(new \DateTime($year . '-01-01 12:00:00'))
->setValeurFonciere((float) $valeurFonciere)
->setCodePostal($codePostal)
->setNomCommune($nomCommune)
->setCodeCommune($codeInsee)
->setCodeDepartement($codeDpt)
// ->setNombreLots((int) $row['nombre_lots'])
->setTypeLocal($typeBien)
->setNombrePiecesPrincipales((int) $nbPieces)
->setSurfaceReelleBati((float) $surface)
// ->setNatureCulture($row['nature_culture'])
// ->setSurfaceTerrain((float) $row['surface_terrain'])
->setLatitude((float) $latitude)
->setLongitude((float) $longitude)
->setCodeTypeLocal($codeTypeLocal)
->setPmc(null);
$this->entityManager->persist($dvf);
$this->entityManager->flush();
return new JsonResponse($dvf);
}
/**
* Check Ville if valid
* @return Ville
*/
protected function validVille()
{
$rVille = $this->entityManager->getRepository(Ville::class);
$cp = $this->request->query->get('cp');
$villeSlug = $this->request->query->get('ville_slug');
$codeInsee = $this->request->query->get('code_insee');
if(is_null($villeSlug) || $villeSlug === "") {
$this->errors[] = "ville_slug non valide";
}
if(is_null($cp) || $cp === "") {
$this->errors[] = "cp non valide";
}
if(in_array($villeSlug, ['marseille','paris','lyon'])) {
$villeSlug = $villeSlug . '-' . substr($cp, -2);
}
$ville = $rVille->findOneByMultipleFields($cp,$villeSlug);
if (!$ville instanceof Ville) {
$resultVille = $rVille->getVilleByCodeInsee($codeInsee);
$ville = !empty($resultVille) ? $resultVille[0] : null;
if (!$ville instanceof Ville) {
$this->errors[] = 'Ville not found for cp : ' . $this->request->query->get('cp')
. ' ville_slug : ' . $this->request->query->get('ville_slug');
}
}
return $ville;
}
/**
* Check param Type is valid
*/
protected function validType()
{
if (!in_array($this->request->query->get('type'), ['maison', 'appartement'])) {
$this->errors[] = 'type non invalide ' . $this->request->query->get('type');
}
}
/**
* Check offre is valid
*/
protected function validOffre()
{
if (!in_array($this->request->query->get('offre'), ['location', 'vente'])) {
$this->errors[] = 'offre non valide : '
. $this->request->query->get('offre');
}
}
/**
* Check year is valid
*/
protected function validYear()
{
if (!in_array((int) $this->request->query->get('year'), [2022, 2021, 2020, 2019, 2018, 2017, 2016,'all'])) {
throw new \UnexpectedValueException('year non valide : '
. $this->request->query->get('year'));
}
}
}