简体   繁体   中英

EasyAdmin 3: how to retrieve edit form values

I am using EasyAdmin 3 and I am trying to create a validation system where:

  • ROLE_EDITOR can edit an Entity (eg Operateur) via EasyAdmin (OperateurCrudCrontroller) and the edited data of this Operator is saved in another temporary table (Operateur_Temp).
  • Later on, ROLE_ADMIN can access the saved data in Operateur_Temp via EasyAdmin, and validate the changes. The validated changes will be added to the Operateur table.

In the OperateurCrudController, I have created a button updateOperator and a function associated to this button called saveOperator.

I can create a new OperateurTemp object and save some data in it. My problem is that I do not know how to get the data from the edit form in EasyAdmin. I would like to retrieve the values of all the fields in the edit form to be able to save them in the OperateurTemp table.

Here is my OperateurCrudController:

<?php

namespace App\Controller\Admin;

use App\Entity\Operateur;
use App\Entity\OperateurTemp;
use App\Entity\User;
use App\Form\OperateurType;
use EasyCorp\Bundle\EasyAdminBundle\Dto\ActionDto;
use EasyCorp\Bundle\EasyAdminBundle\Dto\CrudDto;
use EasyCorp\Bundle\EasyAdminBundle\Form\Type\CrudFormType;
use EasyCorp\Bundle\EasyAdminBundle\Provider\AdminContextProvider;
use EasyCorp\Bundle\EasyAdminBundle\Router\CrudUrlGenerator;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use App\Repository\OperateurRepository;
use App\Repository\OperateurTempRepository;
use App\Repository\UserRepository;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\QueryBuilder;
use EasyCorp\Bundle\EasyAdminBundle\Collection\FieldCollection;
use EasyCorp\Bundle\EasyAdminBundle\Collection\FilterCollection;
use EasyCorp\Bundle\EasyAdminBundle\Config\Filters;
use EasyCorp\Bundle\EasyAdminBundle\Config\KeyValueStore;
use EasyCorp\Bundle\EasyAdminBundle\Context\AdminContext;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;


use EasyCorp\Bundle\EasyAdminBundle\Dto\EntityDto;
use EasyCorp\Bundle\EasyAdminBundle\Dto\SearchDto;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
use EasyCorp\Bundle\EasyAdminBundle\Field\IdField;
use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField;
use EasyCorp\Bundle\EasyAdminBundle\Field\DateTimeField;
use EasyCorp\Bundle\EasyAdminBundle\Field\NumberField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextareaField;
use EasyCorp\Bundle\EasyAdminBundle\Field\EmailField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TelephoneField;
use EasyCorp\Bundle\EasyAdminBundle\Field\UrlField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextEditorField;

use EasyCorp\Bundle\EasyAdminBundle\Config\Action;
use EasyCorp\Bundle\EasyAdminBundle\Config\Actions;
use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
use EasyCorp\Bundle\EasyAdminBundle\Filter\EntityFilter;
use EasyCorp\Bundle\EasyAdminBundle\Router\AdminUrlGenerator;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Validator\Constraints\Date;

use EasyCorp\Bundle\EasyAdminBundle\Event\BeforeEntityUpdatedEvent;
use EasyCorp\Bundle\EasyAdminBundle\Event\BeforeCrudActionEvent;
use EasyCorp\Bundle\EasyAdminBundle\Factory\EntityFactory;
use EasyCorp\Bundle\EasyAdminBundle\Event\AfterCrudActionEvent;
use EasyCorp\Bundle\EasyAdminBundle\Orm\EntityUpdater;
use EasyCorp\Bundle\EasyAdminBundle\Event\AfterEntityUpdatedEvent;
use EasyCorp\Bundle\EasyAdminBundle\Event\BeforeEntityPersistedEvent;
use App\EventSubscriber\EasyAdminSubscriber;

class OperateurCrudController extends AbstractCrudController
{

    private $adminContextProvider;
    private $entityManager;

    public function __construct(AdminUrlGenerator $adminUrlGenerator, AdminContextProvider $adminContextProvider, EntityManagerInterface $entityManager)
    {
        $this->adminUrlGenerator = $adminUrlGenerator;
        $this->adminContextProvider = $adminContextProvider;
        $this->entityManager = $entityManager;
    }

    public static function getEntityFqcn(): string
    {
        return Operateur::class;
    }

    public function configureFields(string $pageName): iterable
    {
        return [
            IdField::new('id')->hideOnForm(),
            TextField::new('name', 'Nom'),
            TextEditorField::new('description', 'Description')->hideOnIndex(),
            TextareaField::new('address', 'Adresse'),
            TextField::new('city', 'Ville')->hideOnIndex(),
            TextField::new('postal_code', 'Code Postal')->hideOnIndex(),
            TextField::new('email', 'Email'),
            TelephoneField::new('phone', 'Téléphone'),
            UrlField::new('website', 'Site Web')->hideOnIndex(),
            TextEditorField::new('opening_hours', 'Horaires d\'Ouverture'),
            NumberField::new('latitude', 'Latitude')->hideOnIndex()->setNumDecimals(15),
            NumberField::new('longitude', 'Longitude')->hideOnIndex()->setNumDecimals(15),
            TextField::new('slug', 'Slug')->hideOnIndex()->setPermission('ROLE_ADMIN'),
            DateTimeField::new('created_at', 'Date Création')->onlyOnIndex(),
            DateTimeField::new('updated_at', 'Date Modification')->onlyOnIndex(),
            AssociationField::new('thematiques', 'Thématiques')

        ];
    }

    public function configureActions(Actions $actions): Actions
    {
        $batchAction = Action::new('approve', 'Approuver', 'fa fa-user-check')
            ->linkToUrl('approveOperators');

        $updateOperator = Action::new('update', 'Enregistrer les modifications', 'fa fa-save')
            ->linkToCrudAction('saveOperator');


        if ($this->isGranted('ROLE_ADMIN')) {
            return $actions
                // ->add(Crud::PAGE_INDEX, $batchAction)
                ->add(Crud::PAGE_INDEX, Action::DETAIL)
                ->setPermission(Action::DELETE, 'ROLE_ADMIN')
                ->setPermission(Action::NEW, 'ROLE_ADMIN')
                ->setPermission(Action::EDIT, 'ROLE_ADMIN')
                ->setPermission($batchAction, 'ROLE_ADMIN');
        }

        if ($this->isGranted('ROLE_EDITOR')) {
            return $actions
                ->add(Crud::PAGE_INDEX, Action::DETAIL)
                ->add(Crud::PAGE_EDIT, $updateOperator)
                ->setPermission(Action::DELETE, 'ROLE_ADMIN')
                ->setPermission(Action::NEW, 'ROLE_ADMIN')
                ->setPermission($updateOperator, 'ROLE_EDITOR')
                ->disable(Action::SAVE_AND_RETURN, Action::SAVE_AND_CONTINUE);
        }
    }

    public function approveOperators(): Response
    {
        $this->addFlash('notice', '<span style="color: green"><i class="fa fa-check"></i>Modification effecuté </span>');

        $url = $this->adminUrlGenerator
            ->setAction(Action::INDEX)
            ->generateUrl();

        return $this->redirect($url);
    }

    public function saveOperator(AdminContext $context): Response
    {   
        $operator = $context->getEntity()->getInstance();

        $operator_name = $operator->getName();
        $operator_description = $operator->getDescription();
        $operator_latitude = $operator->getLatitude();
        $operator_longitude = $operator->getLongitude();

        $operator_temp = new OperateurTemp();
        $operator_temp->setName($operator_name);
        $operator_temp->setDescription($operator_description);
        $operator_temp->setLatitude($operator_latitude);
        $operator_temp->setLongitude($operator_longitude);

        $em = $this->getDoctrine()->getManager();
        $em->persist($operator_temp);
        $em->flush();

        //$this->addFlash('notice', '<span style="color: green"><i class="fa fa-check"></i>Modification prise en compte ! </span>');

        //Create my own save button in page edit

        $url = $this->adminUrlGenerator
            ->setAction(Action::INDEX)
            ->generateUrl();

        return $this->redirect($url);
    }


    public function configureCrud(Crud $crud): Crud
    {
        return $crud
            ->setEntityPermission('ROLE_EDITOR');
    }



    public function createIndexQueryBuilder(SearchDto $searchDto, EntityDto $entityDto, FieldCollection $fields, FilterCollection $filters): QueryBuilder
    {
        $response = parent::createIndexQueryBuilder($searchDto, $entityDto, $fields, $filters);
        if (!$this->isGranted('ROLE_ADMIN')) {
            $response->where('entity.id = :id');
            $response->setParameter('id', $this->getUser()->getOperateur());
        }

        return $response;
    }

    public function updateEntity(EntityManagerInterface $entityManager, $entityInstance): void
    {
        parent::updateEntity($entityManager, $entityInstance); // TODO: Change the autogenerated stub
    }
}

I have tried to use EasyAdminSubscriber and the BeforeEntityUpdatedEvent; but it did not worked. I get the impression that the updateOperateur function is never executed. Here is my EasyAdminSubscriber.php file:

<?php

namespace App\EventSubscriber;

use App\Entity\User;
use App\Entity\Operateur;
use App\Entity\OperateurTemp;
use Doctrine\ORM\EntityManagerInterface;
use EasyCorp\Bundle\EasyAdminBundle\Event\BeforeEntityPersistedEvent;
use EasyCorp\Bundle\EasyAdminBundle\Event\BeforeEntityUpdatedEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;

class EasyAdminSubscriber implements EventSubscriberInterface
{

    private $entityManager;
    private $passwordEncoder;

    public function __construct(EntityManagerInterface $entityManager, UserPasswordEncoderInterface $passwordEncoder)
    {
        $this->entityManager = $entityManager;
        $this->passwordEncoder = $passwordEncoder;
    }

    public static function getSubscribedEvents()
    {
        return [
            BeforeEntityPersistedEvent::class => ['addUser'],
            BeforeEntityUpdatedEvent::class => ['updateUser'],
            BeforeEntityUpdatedEvent::class => ['updateOperateur'],
        ];
    }

    public function updateUser(BeforeEntityUpdatedEvent $event)
    {
        $entity = $event->getEntityInstance();

        if (!($entity instanceof User)) {
            return;
        }
        $this->setPassword($entity);
    }

    public function updateOperateur(BeforeEntityUpdatedEvent $event)
    {
        $entity = $event->getEntityInstance();
        if (!($entity instanceof Operateur)) {
            return;
        }
        $this->setOperateurTemp($entity);
    }

    public function addUser(BeforeEntityPersistedEvent $event)
    {
        $entity = $event->getEntityInstance();

        if (!($entity instanceof User)) {
            return;
        }
        $this->setPassword($entity);
    }

    /**
     * @param User $entity
     */
    public function setPassword(User $entity): void
    {
        $pass = $entity->getPassword();

        $entity->setPassword(
            $this->passwordEncoder->encodePassword(
                $entity,
                $pass
            )
        );
        $this->entityManager->persist($entity);
        $this->entityManager->flush();
    }

    /**
     * @param Operateur $entity
     */
    public function setOperateurTemp(Operateur $entity): void
    {
        $operator_temp = new OperateurTemp();

        $operator_temp->setName($entity->getName());
        $operator_temp->setDescription($entity->getDescription());
        $operator_temp->setLatitude($entity->getLatitude());
        $operator_temp->setLongitude($entity->getLongitude());

        var_dump($entity);
        var_dump($operator_temp);

        $this->entityManager->persist($operator_temp);
        $this->entityManager->flush();
    }
}

I have been also checking the AbstractCrudController.php file in the EasyAdminBundle file to check the main edit, new, etc. functions to know how to retrieve the form values or how to get the form and its attributes, but without success.

If anyone know how to get the edit form and its values in EasyAdmin 3, it would be hardly appreciated.

Thanks in advance

i cant comment so i answer instead. here is my proposal.

Use BeforeEntityUpdatedEvent. Make a validate boolean field, setup it as false if role = ROLE_EDITOR.

ROLE_ADMIN have to be able to see this validate field and just have to change it. So add in your entity the nullable field, and in the controller this:

  BooleanField::new('Validate')->setPermission('ROLE_ADMIN')

Once this is done, setup your BeforeEntityPersistedEvent

public function prePostChargeActuelle(BeforeEntityPersistedEvent $event){

    $entity=$event->getEntityInstance();

    $user = $this->getUser();
    $userRole = $user->getRole();

    if ($entity instanceof Operateur) {

           if($userRole == "ROLE_EDITOR){
                    $entity->setValidate(false);
             }
    }

And to prevent these non validate operators to be displayed in your crud for the wrong user , create in your repository :

 public function getValidateOperator($user,$role)
    {
      if($role == "ROLE_ADMIN"){
        return $this->createQueryBuilder('t')
          ->select('t')
          ->andWhere('t.validate = false')
          ->orderBy('t.id', 'DESC')
          ->setMaxResults(5)
          ->getQuery()
          ->getResult()
          ;
      }elseif($role == "ROLE_EDITOR"){
        return $this->createQueryBuilder('t')
        ->select('t')
        ->andWhere('t.validate = false')
        ->orderBy('t.id', 'DESC')
        ->setMaxResults(5)
        ->getQuery()
        ->getResult()
          ;
      }

Add this in your crudController the field to display it:

TextField::new('getNonValidateOperator'),

So you have your validate object visible only by editor or whatever other role you want instead, and the no validate only visible by admin, which will have to validate it. My code maybe contain some mistake and can be way better/clean, I did it quickly. Feel free to ask me if you dont understand something !

Have You considered different ways to accomplish that? Maybe You should create another class (OperatorEdited) that will extend the operator class with an additional boolean value, like $isValid. Then in Your operator CRUD Controller instead of updating the current instance of the operator create a new OperatorEdit instance with $isValided = false. You will have those data separated.

After another editor validate the edition of the Operator instance (which is currently stored as OperatorEdit) You will override it and delete the OperatorEdit instance from DB.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM