src/Controller/DataController.php line 69

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  4. use Symfony\Component\HttpFoundation\Request;
  5. use Symfony\Component\HttpFoundation\RequestStack;
  6. use Symfony\Component\HttpFoundation\Response;
  7. use Symfony\Contracts\Translation\TranslatorInterface;
  8. use Symfony\Component\Routing\Annotation\Route;
  9. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  10. use Symfony\Component\String\Slugger\SluggerInterface;
  11. use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
  12. use Symfony\Component\Form\Extension\Core\Type\TextType;
  13. use Symfony\Component\HttpFoundation\File\Exception\FileException;
  14. use Doctrine\ORM\EntityManagerInterface;
  15. use Eckinox\DataToEntityBundle\Controller\DataToEntityController;
  16. use Eckinox\CoreBundle\Service\Logger;
  17. use App\Form\Type\DataType;
  18. use App\Entity\Graveyard;
  19. use App\Entity\Spouse;
  20. use App\Entity\MemorialCard;
  21. use App\Entity\Person;
  22. use App\Entity\Census;
  23. use App\Entity\Wedding;
  24. use App\Entity\ImportData;
  25. use App\Entity\Photo;
  26. class DataController extends DataToEntityController
  27. {
  28.     /**
  29.      * @var Request
  30.      */
  31.     private $request;
  32.     /**
  33.      * @var TranslatorInterface
  34.      */
  35.     private $translator;
  36.     /**
  37.      * @var SluggerInterface
  38.      */
  39.     private $slugger;
  40.     /**
  41.      * @var Logger
  42.      */
  43.     private $logger;
  44.     public function __construct(
  45.         RequestStack $requestStack
  46.         TranslatorInterface $translator
  47.         SluggerInterface $slugger
  48.         Logger $logger,
  49.         EntityManagerInterface $entityManager
  50.     ) {
  51.         parent::__construct($entityManager);
  52.         $this->request $requestStack->getCurrentRequest();
  53.         $this->translator $translator;
  54.         $this->slugger $slugger;
  55.         $this->logger $logger;
  56.     }
  57.     /**
  58.      * @Route("/", name="dashboard")
  59.      */
  60.     public function dashboard(): Response
  61.     {
  62.         return $this->redirectToRoute('genaise_upload_data');
  63.     }
  64.     /**
  65.      * @Route("/data/upload", name="genaise_upload_data")
  66.      */
  67.     public function upload(): Response
  68.     {
  69.         $form $this->createForm(DataType::class);
  70.         $date = new \DateTime();
  71.         $data = [
  72.             'memorial_card' => MemorialCard::class,
  73.             'graveyard' => Graveyard::class,
  74.             'person' => Person::class,
  75.             'census' => Census::class
  76.         ];
  77.         $form->handleRequest($this->request);
  78.         if ($form->isSubmitted() && $form->isValid()) {
  79.             foreach ($data as $dataName => $entityClass) {
  80.                 $file $form->get($dataName)->get($dataName '_file')->getData();
  81.                 
  82.                 if ($file !== null) {
  83.                     $importData = new ImportData();
  84.                     $originalFileName sprintf('%s.%s'pathinfo($file->getClientOriginalName(), PATHINFO_FILENAME), $file->guessExtension());
  85.                     $fileName sprintf('%s_%s.%s'$dataName$date->format('YmdHis'), $file->guessExtension());
  86.                     try {
  87.                         $file->move(
  88.                             $this->getParameter('import_data_directory'),
  89.                             $fileName
  90.                         );
  91.                         $importData->setFilePath($this->getParameter('import_data_directory').$fileName);
  92.                         $importData->setEntityClass($entityClass);
  93.                         $this->entityManager->persist($importData);
  94.                         $this->entityManager->flush();
  95.                         $this->addFlash('success'$this->translator->trans(
  96.                             'data.messages.file_has_been_uploaded'
  97.                             [ '%fileName%' => $originalFileName ]
  98.                         ));
  99.                     } catch (FileException $e) {
  100.                         $this->addFlash('error'$this->translator->trans(
  101.                             'data.messages.file_upload_failed'
  102.                             [ '%fileName%' => $originalFileName ]
  103.                         ));
  104.                     }
  105.                 }
  106.             }
  107.         }
  108.         return $this->render('genaise/data/form.html.twig', [
  109.             'form' => $form->createView(),
  110.             'import_data' => $this->entityManager->getRepository(ImportData::class)->findBy([ 'executedAt' => null ])
  111.         ]);
  112.     }
  113.     /**
  114.      * @Route("/cron/import-data", name="genaise_cron_import_data")
  115.      */
  116.     public function import(): Response
  117.     {
  118.         ini_set('memory_limit''1000M');
  119.         ini_set('max_execution_time''0');
  120.         $this->entityManager->getConnection()->getConfiguration()->setSQLLogger(null);
  121.         $this->logger->disableOnFlushEvent();
  122.         $this->enableDetachEntity();
  123.         $importData $this->entityManager->getRepository(ImportData::class)->findBy([ 'executedAt' => null ]);
  124.         foreach ($importData as $import) {
  125.             $timeStart microtime(true);
  126.             $executedAt = new \DateTime('now');
  127.             if (file_exists($import->getFilePath())) {
  128.                 $data = [];
  129.                 $file fopen($import->getFilePath(), 'r');
  130.                 $repository $this->entityManager->getRepository($import->getEntityClass());
  131.                 $repository->deleteAll();
  132.                 while (!feof($file)) {
  133.                     $row fgetcsv($file0';');
  134.                     if ($row) { $data[] = $row; }
  135.                     if (count($data) >= 10000 || feof($file)) {
  136.                         $this->saveToEntity($import->getEntityClass(), $data);
  137.                         if ($import->getEntityClass() === Person::class) {
  138.                             $this->handleWeddings($data);
  139.                         } else if ($import->getEntityClass() === Graveyard::class) {
  140.                             $this->handleSpouses($data);
  141.                         }
  142.                         $data = [];
  143.                     }
  144.                 }
  145.                 fclose($file);
  146.                 // Match photos
  147.                 if ($import->getEntityClass() === Graveyard::class) {                 
  148.                     $this->matchGraveyardsPhotos();    
  149.                 } else if ($import->getEntityClass() === MemorialCard::class) {
  150.                     $this->matchMemorialCardsPhotos();    
  151.                 }
  152.             }
  153.             $import->setExecutedAt($executedAt);
  154.             $import->setExecutionTime(microtime(true) - $timeStart);
  155.             $this->entityManager->persist($import);
  156.             $this->entityManager->flush();
  157.         }
  158.         $this->logger->enableOnFlushEvent();
  159.         return new Response('done');
  160.     }
  161.     /**
  162.      * @Route("/api/rest/graveyards/names", name="genaise_api_graveyards_names")
  163.      */
  164.     public function getGraveyardsNames(): Response
  165.     {
  166.         return $this->json([
  167.             'status' => 'success',
  168.             'data' => $this->entityManager->getRepository(Graveyard::class)->findNames()
  169.         ]);
  170.     }
  171.     /**
  172.      * @Route("/api/rest/census/cities", name="genaise_api_census_cities")
  173.      */
  174.     public function getCensusCities(): Response
  175.     {
  176.         return $this->json([
  177.             'status' => 'success',
  178.             'data' => $this->entityManager->getRepository(Census::class)->findCities()
  179.         ]);
  180.     }
  181.     /**
  182.      * @Route("/api/rest/census/years", name="genaise_api_census_years")
  183.      */
  184.     public function getCensusYears(): Response
  185.     {
  186.         return $this->json([
  187.             'status' => 'success',
  188.             'data' => $this->entityManager->getRepository(Census::class)->findYears()
  189.         ]);
  190.     }
  191.     public function formatData($class$data) {
  192.         foreach ($this->mapping[$class]['fields'] as $dataField => $entityField) {
  193.             if (strpos($entityField['name'], 'date') !== false && isset($data[$dataField])) {
  194.                 $data[$dataField] = $data[$dataField] ? new \DateTime($data[$dataField]) : null;
  195.             }
  196.             if ($entityField['name'] === 'death_year') {
  197.                 $data[$dataField] = $data[$dataField] ? (int) $data[$dataField] : null;
  198.             }
  199.             if ($class === Census::class && in_array($entityField['name'], [ 'number''home''family''line''year' ])) {
  200.                 $data[$dataField] = $data[$dataField] ? (int) $data[$dataField] : null;
  201.             }
  202.         }
  203.         return $data;
  204.     }
  205.     private function handleWeddings(array $rows) {
  206.         $data = [];
  207.         foreach ($rows as $row) {
  208.             $weddings = [];
  209.             $rowNumber 18;
  210.             $verifiedRowNumber 60;
  211.             // Handle the three weddings
  212.             foreach ([ 12] as $number) {
  213.                 $wedding = [
  214.                     'number' => $number,
  215.                     'marital_status' => $row[$rowNumber++],
  216.                     'date' => $row[$rowNumber++],
  217.                     'place' => $row[$rowNumber++],
  218.                     'spouse_first_name' => $row[$rowNumber++],
  219.                     'spouse_last_name' => $row[$rowNumber++],
  220.                     'spouse_father_full_name' => $row[$rowNumber++],
  221.                     'spouse_mother_full_name' => $row[$rowNumber++],
  222.                     'notes' => $row[$rowNumber++],
  223.                     'references' => $row[$rowNumber++],
  224.                     'document' => $row[$rowNumber++],
  225.                     'verified' => $row[$verifiedRowNumber++],
  226.                 ];
  227.                 if ($wedding['spouse_first_name'] || $wedding['spouse_last_name']) {
  228.                     $weddings[] = $wedding;
  229.                 }
  230.             }
  231.             if ($weddings) {
  232.                 $person $this->entityManager->getRepository(Person::class)->findOneBy([
  233.                     'number' => $row[0],
  234.                     'usualFirstName' => $row[4],
  235.                     'lastName' => $row[6]
  236.                 ]);
  237.                 foreach ($weddings as $key => $wedding) {
  238.                     $weddings[$key]['person'] = $person;
  239.                     $data[] = $weddings[$key];
  240.                 }
  241.             }
  242.         }
  243.         $this->saveToEntity(Wedding::class, $data);
  244.         $this->detachEntity(Wedding::class);
  245.         $data = [];
  246.         return $this;
  247.     }
  248.     private function handleSpouses(array $rows) {
  249.         $data = [];
  250.         foreach ($rows as $row) {
  251.             $spouses = [];
  252.             $rowNumber 3;
  253.             // Handle the two spouses
  254.             foreach ([ 1] as $number) {
  255.                 $spouse = [
  256.                     'number' => $number,
  257.                     'last_name' => $row[$rowNumber++],
  258.                     'first_name' => $row[$rowNumber++],
  259.                 ];
  260.                 if ($spouse['first_name'] && $spouse['last_name']) {
  261.                     $spouses[] = $spouse;
  262.                 }
  263.             }
  264.             if ($spouses) {
  265.                 $graveyard $this->entityManager->getRepository(Graveyard::class)->findOneBy([
  266.                     'number' => $row[0],
  267.                     'lastName' => $row[1],
  268.                     'firstName' => $row[2]
  269.                 ]);
  270.                 foreach ($spouses as $key => $spouse) {
  271.                     $spouses[$key]['graveyard'] = $graveyard;
  272.                     $data[] = $spouses[$key];
  273.                 }
  274.             }
  275.         }
  276.         $this->saveToEntity(Spouse::class, $data);
  277.         $this->detachEntity(Spouse::class);
  278.         $data = [];
  279.         return $this;
  280.     }
  281.     private function matchGraveyardsPhotos() {
  282.         $date = (new \DateTime('now'))->setTime(00);
  283.         $photoRepository $this->entityManager->getRepository(Photo::class);
  284.         $graveyardRepository $this->entityManager->getRepository(Graveyard::class);
  285.         $graveyardsIds $graveyardRepository->findIds();
  286.         $count count($graveyardsIds);
  287.         $persistedCount 0;
  288.         foreach ($graveyardsIds as $key => $id) {
  289.             $isLast $key == $count 1;
  290.             // We have to refresh the graveyard entity because it was detached
  291.             $graveyard $graveyardRepository->find($id);
  292.             if ($graveyard->getPhotoNumber()) {
  293.                 $key sprintf('cimetieres-%s-%s'$graveyard->getGraveyardName(), $graveyard->getPhotoNumber());
  294.                 $slug strtolower($this->slugger->slug($key));
  295.                 $photo $photoRepository->findOneBy([ 
  296.                     'slug' => $slug
  297.                     'number' => $graveyard->getPhotoNumber() 
  298.                 ]);
  299.                 if ($photo) {
  300.                     $graveyard->addPhoto($photo);
  301.                     $this->entityManager->persist($graveyard);
  302.                     $persistedCount++;
  303.                 }
  304.             }
  305.             if ($persistedCount >= 200 || $isLast) {
  306.                 $this->entityManager->flush();
  307.                 $this->detachEntity(Graveyard::class);
  308.                 $persistedCount 0;
  309.             }
  310.         }
  311.         return $this;
  312.     }
  313.     private function matchMemorialCardsPhotos() {
  314.         $date = (new \DateTime('now'))->setTime(00);
  315.         $photoRepository $this->entityManager->getRepository(Photo::class);
  316.         $memorialCardRepository $this->entityManager->getRepository(MemorialCard::class);
  317.         $memorialCardsIds $memorialCardRepository->findIds();
  318.         $count count($memorialCardsIds);
  319.         $persistedCount 0;
  320.         foreach ($memorialCardsIds as $key => $id) {
  321.             $isLast $key == $count 1;
  322.             // We have to refresh the memorial card entity because it was detached
  323.             $memorialCard $memorialCardRepository->find($id);
  324.             if ($memorialCard->getNumber()) {
  325.                 $key sprintf('cartes-mortuaires-%s-'$memorialCard->getNumber());
  326.                 $slug strtolower($this->slugger->slug($key));
  327.                 $photo $photoRepository->findOneBy([ 
  328.                     'slug' => $slug
  329.                     'number' => $memorialCard->getNumber() 
  330.                 ]);
  331.                 if ($photo) {
  332.                     $memorialCard->addPhoto($photo);
  333.                     $this->entityManager->persist($memorialCard);
  334.                     $persistedCount++;
  335.                 }
  336.             }
  337.             if ($persistedCount >= 200 || $isLast) {
  338.                 $this->entityManager->flush();
  339.                 $this->detachEntity(MemorialCard::class);
  340.                 $persistedCount 0;
  341.             }
  342.         }
  343.         return $this;
  344.     }
  345. }