Skip to content

Instantly share code, notes, and snippets.

@aokhrimenko
Last active May 11, 2022 10:08
Show Gist options
  • Save aokhrimenko/021a16d0f27a1a44e432657115759d42 to your computer and use it in GitHub Desktop.
Save aokhrimenko/021a16d0f27a1a44e432657115759d42 to your computer and use it in GitHub Desktop.
Add "Quick create" option for Association fields. Works only with Doctrine ORM mapping in attributes and Uuid as entity identifier. The idea is to create new entity if submitted value is not a valid Uuid.
<?php
namespace App\EventSubscriber;
use App\Entity\SimpleCreate;
use Doctrine\ORM\Mapping\ManyToOne;
use Doctrine\Persistence\ManagerRegistry;
use EasyCorp\Bundle\EasyAdminBundle\Config\Action;
use EasyCorp\Bundle\EasyAdminBundle\Context\AdminContext;
use EasyCorp\Bundle\EasyAdminBundle\Contracts\Controller\CrudControllerInterface;
use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use EasyCorp\Bundle\EasyAdminBundle\Event\BeforeCrudActionEvent;
use Symfony\Component\Uid\Uuid;
class BeforeCrudActionSubscriber implements EventSubscriberInterface
{
public function __construct(private ManagerRegistry $doctrine, private ContainerInterface $container)
{
}
public static function getSubscribedEvents()
{
return [
BeforeCrudActionEvent::class => 'onBeforeCrudActionEvent',
];
}
public function onBeforeCrudActionEvent(BeforeCrudActionEvent $event)
{
$context = $event->getAdminContext();
if (!$this->isNewOrEditPage($context) && 'POST' !== $context->getRequest()->getMethod()) {
return;
}
$reflectionClass = new \ReflectionClass($context->getEntity()->getFqcn());
$shortClassName = $reflectionClass->getShortName();
$formData = $context->getRequest()->get($shortClassName);
if (!$formData) {
return;
}
$em = $this->doctrine->getManagerForClass($context->getEntity()->getFqcn());
$crudControllerFqcn = $context->getCrudControllers()->findCrudFqcnByEntityFqcn($context->getEntity()->getFqcn());
/** @var CrudControllerInterface $crudControllerInstance */
$crudControllerInstance = $this->container->get($crudControllerFqcn);
foreach ($crudControllerInstance->configureFields($context->getCrud()->getCurrentPage()) as $field) {
if (!$field instanceof AssociationField) {
continue;
}
$propertyName = $field->getAsDto()->getProperty();
if (!isset($formData[$propertyName])) {
continue;
}
if (Uuid::isValid($formData[$propertyName])) {
continue;
}
$attrs = ($reflectionClass->getProperty($propertyName)->getAttributes(ManyToOne::class));
if (1 !== count($attrs)) {
continue;
}
$args = $attrs[0]->getArguments();
if (!isset($args['targetEntity'])) {
continue;
}
$implements = class_implements($args['targetEntity']);
if (!$implements || !isset($implements[SimpleCreate::class])) {
continue;
}
/** @var SimpleCreate $target */
$target = new $args['targetEntity'];
$target->setText($formData[$propertyName]);
$em->persist($target);
$em->flush();
$formData[$propertyName] = (string)$target->getId();
}
$context->getRequest()->request->set($shortClassName, $formData);
}
private function isNewOrEditPage(AdminContext $context): bool
{
return in_array($context->getCrud()->getCurrentAction(), [Action::NEW, Action::EDIT]);
}
}
<?php
namespace App\Controller\Admin;
use App\Entity\Example;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
class ExampleCrudController extends AbstractCrudController
{
public static function getEntityFqcn(): string
{
return Example::class;
}
public function configureFields(string $pageName): iterable
{
yield TextField::new('name');
yield AssociationField::new('type')
->setFormTypeOption('attr.data-ea-autocomplete-allow-item-create', 'true'); // this option adds "Add" functioality
}
}
<?php
namespace App\Entity;
use Symfony\Component\Uid\Uuid;
interface SimpleCreate
{
public function getId(): ?Uuid;
public function setText(string $text): self;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment