I am using EasyAdmin 3 and I am trying to create a validation system where:
- ROLE_EDITOR can edit an Entity (e.g. 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