src/Admin/LotAdmin.php line 270

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace App\Admin;
  4. use App\Entity\Lot;
  5. use App\Form\SurfaceType;
  6. use App\Service\ImagePdf;
  7. use App\Entity\PieceJointe;
  8. use App\Entity\Programme;
  9. use App\Form\BlockType;
  10. use App\Repository\ProgrammeRepository;
  11. use Sonata\AdminBundle\FieldDescription\FieldDescriptionInterface;
  12. use Sonata\Form\Type\CollectionType;
  13. use Sonata\Form\Type\DatePickerType;
  14. use Sonata\AdminBundle\Form\FormMapper;
  15. use Sonata\AdminBundle\Datagrid\ListMapper;
  16. use Sonata\AdminBundle\Datagrid\DatagridMapper;
  17. use Sonata\AdminBundle\Datagrid\DatagridInterface;
  18. use Sonata\AdminBundle\Datagrid\ProxyQueryInterface;
  19. use Sonata\AdminBundle\Route\RouteCollectionInterface;
  20. use Symfony\Bridge\Doctrine\Form\Type\EntityType;
  21. use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
  22. use Symfony\Component\Form\Extension\Core\Type\MoneyType;
  23. use Symfony\Component\Form\Extension\Core\Type\ButtonType;
  24. use Symfony\Component\Form\Extension\Core\Type\TextareaType;
  25. use Symfony\Component\HttpFoundation\File\Exception\FileException;
  26. final class LotAdmin extends AbstractAdmin
  27. {
  28.     protected $datagridValues = [
  29.         '_page' => 1,
  30.         '_sort_order' => 'DESC',
  31.         '_sort_by' => 'id',
  32.         '_per_page' => 250,
  33.     ];
  34.     private $tokenStorage;
  35.     public function setSecurityTokenStorage($tokenStorage)
  36.     {
  37.         $this->tokenStorage $tokenStorage;
  38.     }
  39.     public function getUser()
  40.     {
  41.         $token $this->tokenStorage->getToken();
  42.         if (null !== $token) {
  43.             return $token->getUser();
  44.         }
  45.         return null;
  46.     }
  47.     protected function configureDefaultFilterValues(array &$filterValues): void
  48.     {
  49.         /*$filterValues['statut'] = [
  50.             'type'  => null,
  51.             'value' => 'libre'
  52.         ];*/
  53.     }
  54.     protected function configureDefaultSortValues(array &$sortValues): void
  55.     {
  56.         $sortValues[DatagridInterface::PAGE] = 1;
  57.         $sortValues[DatagridInterface::SORT_ORDER] = 'ASC';
  58.         $sortValues[DatagridInterface::SORT_BY] = 'statut';
  59.         $sortValues[DatagridInterface::PER_PAGE] = 250;
  60.     }
  61.     protected function configureBatchActions(array $actions): array
  62.     {
  63.         if(!in_array("ROLE_SUPERADMIN"$this->getUser()->getRoles()))
  64.             unset($actions["delete"]) ;
  65.         return $actions;
  66.     }
  67.     protected function configureRoutes(RouteCollectionInterface $collection): void
  68.     {
  69.         $collection->remove('show');
  70.         $collection->add('clone'$this->getRouterIdParameter() . '/clone');
  71.         if ($this->isChild()) {
  72.             return;
  73.         }
  74.         // This is the route configuration as a parent
  75.         $collection->clear();
  76.     }
  77.     public function configureQuery(ProxyQueryInterface $query): ProxyQueryInterface
  78.     {
  79.         return $query;
  80.     }
  81.     public function prePersist(object $lot): void
  82.     {
  83.         $request $this->getRequest();
  84.         $files $request->files->get($this->getForm()->getName());
  85.         if (isset($files['pjs'])) {
  86.             $this->managePiecesJointes($files['pjs'], $lot);
  87.         }
  88.         $programme $lot->getProgrammeParent();
  89.         if ($programme) {
  90.             $lot->setAdresse($programme->getAdresse());
  91.             $lot->setVille($programme->getVille());
  92.             $lot->setCodePostal($programme->getCodePostal());
  93.             $lot->setLatitude($programme->getLatitude());
  94.             $lot->setLongitude($programme->getLongitude());
  95.             $lot->setProgramme($programme->getNom());
  96.             $lot->setImage($programme->getImage());
  97.             $lot->setBrochure($programme->getBrochure());
  98.             $lot->setPlanMasse($programme->getPlanMasse());
  99.             $lot->setPromoteur($programme->getPromoteur());
  100.         }
  101.     }
  102.     public function preUpdate(object $lot): void
  103.     {
  104.         $files $this->getRequest()->files->get($this->getForm()->getName());
  105.         $fields $this->getRequest()->request->get($this->getForm()->getName());
  106.         if(isset($files['pjs'])) $this->managePiecesJointes($files['pjs'], $lot);
  107.     }
  108.     private function managePiecesJointes($pjs$lot) {
  109.         $lotPjs $lot->getPjs()->toArray();
  110.         foreach($pjs as $n => $pj) {
  111.             // Uniquement sur PJ sans fichiers == ajouter dans cette condition ""&& $lot->getPjs()[$n]->getFilename() == null"
  112.             if($pj['fichier'] && isset($lotPjs[$n])) {
  113.                 $fichier $pj['fichier'];
  114.                 $originalFilename pathinfo($fichier->getClientOriginalName(), PATHINFO_FILENAME);
  115.                 $safeFilename $this->slugify($originalFilename);
  116.                 $newFilename $safeFilename '-' uniqid() . '.' $fichier->guessExtension();
  117.                 try {
  118.                     $fichier->move(PieceJointe::SAVE_PATH$newFilename);
  119.                 } catch (FileException $e) {
  120.                     // ... handle exception if something happens during file upload
  121.                 }
  122.                 if(strpos($newFilename'.pdf') !== false) {
  123.                     $newFilename ImagePdf::convertToImage(PieceJointe::SAVE_PATH.$newFilename);
  124.                 }
  125.                 $lot->getPjs()[$n]->setFilename($newFilename);
  126.             }
  127.         }
  128.     }
  129.     protected function configureDatagridFilters(DatagridMapper $filter): void
  130.     {
  131.         $filter
  132.             ->add('reference'null, [
  133.                 'show_filter' => true,
  134.                 'label' => 'Réf. LOT'
  135.             ])
  136.             ->add('statut'null, [
  137.                 'show_filter' => true,
  138.                 'field_type' => ChoiceType::class,
  139.                 'field_options' => [
  140.                     'choices' => Lot::getStatutsForForm(),
  141.                 ],
  142.             ])
  143.             ->add('typeMoteurRecherche')
  144.             ->add('promoteur')
  145.             ->add('superficie')
  146.             ->add('terrasse')
  147.             ->add('prix')
  148.             ->add('fraisNotaireInclus')
  149.             ->add('annexes')
  150.             ->add('livraison')
  151.             ->add('adresse')
  152.             ->add('ville')
  153.             ->add('codePostal')
  154.             ;
  155.     }
  156.     protected function configureListFields(ListMapper $list): void
  157.     {
  158.         $list
  159.             ->addIdentifier('reference'null, [
  160.                 'label' => 'Réf. LOT',
  161.                 'route' => ['name' => 'edit'],
  162.                 'template' => 'sonata/list_fields/list_lot_target_blank.html.twig'
  163.             ])
  164.             ->add('_plan''string', [
  165.                 'label' => 'Plan du Lot',
  166.                 'template' => 'sonata/list_fields/list_lot_target_plan.html.twig',
  167.                 'sortable' => false,
  168.                 'mapped' => false,
  169.             ])
  170.             ->addIdentifier('etatLot'null, [
  171.                 'label' => 'Etat de préparation',
  172.                 'template' => 'sonata/list_fields/list_lot_etat.html.twig'
  173.             ])
  174.             ->addIdentifier('statut'null, [
  175.                 'template' => 'sonata/list_fields/list_lot_statut.html.twig'
  176.             ])
  177.             ->addIdentifier('type'null, [
  178.                 'route' => ['name' => 'edit'],
  179.                 'template' => 'sonata/list_fields/list_lot_target_blank.html.twig'
  180.             ])
  181.             ->addIdentifier('prix'FieldDescriptionInterface::TYPE_INTEGER, [
  182.                 'template' => 'sonata/list_fields/list_lot_prix.html.twig'
  183.                 ])
  184.             ->addIdentifier('ville'null, [
  185.                 'route' => ['name' => 'edit'],
  186.                 'template' => 'sonata/list_fields/list_lot_target_blank.html.twig'
  187.             ])
  188.             ->addIdentifier('codePostal'null, [
  189.                 'route' => ['name' => 'edit'],
  190.                 'template' => 'sonata/list_fields/list_lot_target_blank.html.twig'
  191.             ])
  192.             ->add('_action''actions', [
  193.                 'actions' => [
  194.                     'clone' => [
  195.                         'template' => 'sonata/Button/list__action_clone.html.twig',
  196.                     ],
  197.                 ],
  198.             ]);
  199.     }
  200.     protected function configureFormFields(FormMapper $form): void
  201.     {
  202.         $user $this->getUser();
  203.         $isSuperAdmin $user->peutModifierContenu();
  204.         $isNegociateur in_array('ROLE_COMMERCIAL'$user->getRoles()) || in_array('ROLE_PARTENAIRE'$user->getRoles());
  205.         $authorizedClass $isSuperAdmin '' 'unauthorized-input';
  206.         $lot $this->getSubject();
  207.         $programme $lot->getProgrammeParent();
  208.         $programmeNotes $programme $programme->getNoteGlobale() : '';
  209.         $livraisonVisu $programme $programme->getVisuLivraison() : true;
  210.         $form
  211.             ->tab('Lot')
  212.                 ->with('État du lot', ['box_class' => 'inline-fields''class' => 'col-lg-6 etats-lots' . ($isSuperAdmin '' ' unauthorized-docs')])
  213.                     ->add('etatLot'ChoiceType::class, [
  214.                         'choices'  => array_flip(Lot::ETATS_PRODUCTION),
  215.                         'expanded' => true,
  216.                         'multiple' => false,
  217.                         'required' => false,
  218.                         'label_attr' => ['style' => 'display:none;'],
  219.                     ])
  220.                 ->end()
  221.                 ->with('Espace Vide', ['box_class' => 'inline-fields''class' => 'col-lg-6 hide-h4'])
  222.                     ->add('placeholder''Symfony\Component\Form\Extension\Core\Type\TextType', [
  223.                         'label' => false,
  224.                         'attr' => ['style' => 'visibility: hidden;'],
  225.                         'mapped' => false,
  226.                         'required' => false,
  227.                     ])
  228.                 ->end()
  229.                 ->with('Description du bien', ['box_class' => 'inline-fields''class' => 'col-md-6' . ($isSuperAdmin '' ' unauthorized-docs')])
  230.                     ->add('programmeParent'EntityType::class, [
  231.                         'class' => Programme::class,
  232.                         'query_builder' => function (ProgrammeRepository $programmeRepository) {
  233.                             $user $this->getUser();
  234.                             $entreprise $user->getEntreprise();
  235.                             return $programmeRepository->createQueryBuilder('p')
  236.                                 ->where('p.entreprise = :entreprise')
  237.                                 ->setParameter('entreprise'$entreprise);
  238.                         },
  239.                     ])
  240.                     ->add('reference'null, [
  241.                         'label' => 'Réf. LOT'
  242.                     ])
  243.                     // ->add('programme', null, [
  244.                     //     'required' => true,
  245.                     //     'attr' => [
  246.                     //         'placeholder' => 'Ex: Garden park'
  247.                     //     ]
  248.                     // ])
  249.                     ->add('statut',  ChoiceType::class, [
  250.                         'choices' => [
  251.                             'Libre' => 'libre',
  252.                             'Option' => 'option',
  253.                             'Réservé' => 'reserve',
  254.                             'Vendu' => 'vendu',
  255.                         ],
  256.                         'row_attr' => ['class' => $authorizedClass],
  257.                     ])
  258.                     ->add('nature',  ChoiceType::class, [
  259.                         'choices' => [
  260.                             'Appartement' => 'appartement',
  261.                             'Maison' => 'maison',
  262.                             'Terrain' => 'terrain',
  263.                             'Local commercial' => 'local_commercial'
  264.                         ],
  265.                     ])
  266.                     ->add('type'null, [
  267.                         'required' => true,
  268.                         'attr' => [
  269.                             'style' => 'width:60%',
  270.                             'placeholder' => 'Ex: T4'
  271.                         ]
  272.                     ])
  273.                     ->add('typeMoteurRecherche'null, [
  274.                         'label' => 'Type (moteur de recherche)',
  275.                         'required' => false,
  276.                         'attr' => [
  277.                             'style' => 'width:60%',
  278.                             'placeholder' => 'Ex: T4'
  279.                         ]
  280.                     ])
  281.                     ->add('etage'null, [
  282.                         'label' => 'Étage',
  283.                         'attr' => [
  284.                             'style' => 'width:30%'
  285.                         ]
  286.                     ])
  287.                     ->add('etageMoteurRecherche'null, [
  288.                         'label' => 'Étage (moteur de recherche)',
  289.                         'attr' => [
  290.                             'style' => 'width:30%'
  291.                         ]
  292.                     ])
  293.                     // ->add('promoteur', null, [
  294.                     //     'required' => false,
  295.                     //     'attr' => [
  296.                     //         'placeholder' => 'Ex: Vinci'
  297.                     //     ]
  298.                     // ])
  299.                     ->add('orientation'null, [
  300.                         'required' => false,
  301.                         'attr' => [
  302.                             'style' => 'width:80%',
  303.                             'placeholder' => 'Ex: Sud-est'
  304.                         ]
  305.                     ])
  306.                     ->add('superficie'SurfaceType::class, [
  307.                         'required' => false
  308.                     ])
  309.                     ->add('terrasse'SurfaceType::class, [
  310.                         'required' => false,
  311.                         'help' => 'Laisser vide si pas de terrasse.'
  312.                     ])
  313.                     ->add('terrasse2'SurfaceType::class, [
  314.                         'label' => '2ème terrasse',
  315.                         'required' => false,
  316.                         'help' => 'Laisser vide si pas de 2ème terrasse.'
  317.                     ])
  318.                     ->add('jardin'SurfaceType::class, [
  319.                         'label' => 'Jardin',
  320.                         'required' => false,
  321.                         'help' => 'Laisser vide si pas de jardin.'
  322.                     ])
  323.                     ->add('prix'MoneyType::class, [
  324.                         'required' => false,
  325.                         'label' => 'Prix TTC',
  326.                         'attr' => [
  327.                             'data-autonumeric' => 'enabled',
  328.                         ],
  329.                         'row_attr' => ['class' => $authorizedClass],
  330.                     ])
  331.                     ->add('fraisNotaireType'ChoiceType::class, [
  332.                         'choices' => [
  333.                             'Frais de notaire réduits' => 'reduits',
  334.                             'Frais de notaire' => 'standards',
  335.                         ],
  336.                         'label' => 'Type de frais de notaire'
  337.                     ])
  338.                     ->add('fraisNotaireInclus'MoneyType::class, [
  339.                         'required' => false,
  340.                         'label' => 'Frais de notaire',
  341.                         'attr' => [
  342.                             'data-autonumeric' => 'enabled'
  343.                         ],
  344.                         'help' => 'Calcul des frais de notaire automatique.'
  345.                     ])
  346.                     ->add('annexes'null, [
  347.                         'required' => false,
  348.                         'label' => 'Annexe(s)',
  349.                         'attr' => [
  350.                             'placeholder' => 'Ex: Garage, parking',
  351.                         ],
  352.                         'row_attr' => ['class' => $authorizedClass],
  353.                         'help' => 'Laisser vide si pas d\'annexe incluse.'
  354.                     ])
  355.                     ->add('dateLivraison'DatePickerType::class, [
  356.                         'required' => false,
  357.                         'label' => 'Date livraison (moteur de recherche)',
  358.                         'row_attr' => [
  359.                             'style' => !$livraisonVisu 'opacity: 0.75' ''
  360.                         ],
  361.                     ])
  362.                     ->add('livraison'null, [
  363.                         'required' => false,
  364.                         'attr' => [
  365.                             'placeholder' => 'Ex: 4T '.date('Y'),
  366.                         ],
  367.                         'row_attr' => [
  368.                             'class' => $authorizedClass,
  369.                             'style' => !$livraisonVisu 'opacity: 0.75' ''
  370.                         ],
  371.                     ])
  372.                     ->add('noteGlobaleProgramme'TextareaType::class, [
  373.                         'label' => 'Notes Globales',
  374.                         'required' => false,
  375.                         'data' => $programmeNotes,
  376.                         'mapped' => false,
  377.                         'disabled' => true,
  378.                         'attr' => [
  379.                             'rows' => '2',
  380.                             'class' => 'noteglobale',
  381.                         ],
  382.                         'row_attr' => [
  383.                             'style' => 'margin-top: 50px;'
  384.                         ],
  385.                     ])
  386.                     ->add('description'TextareaType::class, [
  387.                         'label' => 'Autres notes sur le lot',
  388.                         'required' => false,
  389.                         'attr' => ['rows' => '2'],
  390.                         'row_attr' => ['class' => $authorizedClass],
  391.                     ])
  392.                 ->end()
  393.                 ->with('Plan du lot', ['box_class' => 'inline-fields''class' => 'col-md-6'])
  394.                     ->add('_planLot'BlockType::class, [
  395.                         'template' => 'sonata/Block/plan_lot.html.twig',
  396.                         'mapped' => false
  397.                     ])
  398.                 ->end()
  399.             ->end();
  400.         $form
  401.         ->tab('Slides')
  402.             ->with('Slides', ['box_class' => 'no-header''class' => 'col-md-12' . (!$isNegociateur '' ' unauthorized-docs')])
  403.                 ->add('pjProgression'ChoiceType::class, [
  404.                     'choices' => array_flip(Lot::INTITULES_PREDEFINIS),
  405.                     'label_attr' => [
  406.                         'class' => 'hide'
  407.                     ],
  408.                     'expanded' => true,
  409.                     'multiple' => true,
  410.                     'attr' => [
  411.                         'class' => 'pjProgression'
  412.                     ]
  413.                 ])
  414.                 ->add('pjs'CollectionType::class, [
  415.                     'label_attr' => [
  416.                         'class' => 'hide'
  417.                     ],
  418.                     'by_reference' => false,
  419.                     'type_options' => [
  420.                         'delete' => true,
  421.                         'delete_options' => [
  422.                             'type'         => ButtonType::class,
  423.                             'type_options' => [
  424.                                 'label' => 'Retirer',
  425.                                 'attr' => [
  426.                                 'class' => 'btn btn-danger btn-delete-elements',
  427.                                 'onclick' => "
  428.                                     if(confirm('Voulez-vous vraiment effacer cette ligne ? N\'oubliez pas d\'enregistrer vos modifications.')) {
  429.                                     $(this).closest('tr').remove();
  430.                                     }
  431.                                 "
  432.                                 ]
  433.                             ]
  434.                         ]
  435.                     ],
  436.                     'row_attr' => [
  437.                         'class' => 'lots-slides'
  438.                     ]
  439.                 ], [
  440.                     'edit' => 'inline',
  441.                     'inline' => 'table',
  442.                     'sortable' => 'ordre'
  443.                 ])
  444.             ->end()
  445.         ->end()
  446.         ;
  447.     }
  448.     public function getExportFormats(): array
  449.     {
  450.         return ['csv''xls'];
  451.     }
  452.     protected function configureExportFields(): array
  453.     {
  454.         return [
  455.             'programmeParent.nom',
  456.             'typeMoteurRecherche',
  457.             'promoteur',
  458.             'superficie',
  459.             'terrasse',
  460.             'prix',
  461.             'annexes',
  462.             'livraison',
  463.             'adresse',
  464.             'ville',
  465.             'codePostal',
  466.             'latitude',
  467.             'longitude',
  468.             'description'
  469.         ];
  470.     }
  471. }