<?php
namespace Roothirsch\CoreBundle\Behaviors\Attributable\EventSubscriber;
use ApiPlatform\Core\Security\ExpressionLanguage;
use Doctrine\ORM\EntityRepository;
use Roothirsch\CoreBundle\Behaviors\Attributable\Form\PreProcessAttributeInterface;
use Roothirsch\CoreBundle\Behaviors\Attributable\MappedSuperclass\AbstractAttributable;
use Roothirsch\CoreBundle\Behaviors\Attributable\MappedSuperclass\AbstractAttribute;
use Roothirsch\CoreBundle\Behaviors\Attributable\MappedSuperclass\AbstractAttributeValue;
use Roothirsch\CoreBundle\Behaviors\Attributable\Service\AttributeTypesService;
use Roothirsch\CoreBundle\Behaviors\Attributable\Type\AttributeTypeInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
class AttributeInjectorEventSubscriber implements EventSubscriberInterface
{
/** @var AbstractAttributable */
private $attributable = null;
/** @var EntityRepository */
private $repository = null;
/**
* @var AttributeTypesService
*/
private $attributeTypes;
/**
* @var TokenStorageInterface
*/
private $tokenStorage;
/**
* AttributeInjectorEventSubscriber constructor.
* @param AttributeTypesService|null $attributeTypes
*/
public function __construct(?AttributeTypesService $attributeTypes, TokenStorageInterface $tokenStorage)
{
$this->attributeTypes = $attributeTypes;
$this->tokenStorage = $tokenStorage;
}
public function setAttributable(AbstractAttributable $attributable): self{
$this->attributable = $attributable;
return $this;
}
public function setRepository(EntityRepository $repository): self{
$this->repository = $repository;
return $this;
}
public static function getSubscribedEvents()
{
return [
FormEvents::PRE_SET_DATA => "buildForm"
];
}
public function buildForm(FormEvent $event){
/** @var Form $form */
$form = $event->getForm();
if(count($this->attributable->attributes()) === 0){
$attributes = $this->repository->findBy([], ['position' => 'ASC']);
$this->attributable->setAttributes($attributes);
}
foreach ($this->attributable->attributes() as $attribute) {
$attributeType = $this->attributeTypes->findByAttribute($attribute);
/** @var AbstractAttribute $attribute */
$options = [
'label' => $attribute,
'required' => $attribute->getRequired(),
'help' => $attribute->getHelp(),
];
if($attributeType){
$attributeType->preAdd($attribute, $options);
}
$this->resolveDefaultValue($options, $attribute);
$form->add(
$attribute->getName(),
$this->attributeTypes->resolveFormType($attribute),
$options
);
if($attributeType){
$attributeType->postAdd($form, $attribute);
}
}
}
private function resolveDefaultValue($options, AbstractAttribute $attribute){
/** @var AbstractAttributeValue $value */
$value = $this->attributable->getAttributeValue($attribute);
$hasDefaultValueAndIsEmpty = $attribute->getDefaultValue() && $value->getValue() === NULL;
if ($hasDefaultValueAndIsEmpty) {
$defaultValue = $attribute->getDefaultValue();
try {
$e = new ExpressionLanguage();
$defaultValue = $e->evaluate($attribute->getDefaultValue(), array_merge(
['user' => $this->tokenStorage->getToken()->getUser()],
$value->resolveExpression()
));
} catch (\Exception $exception){}
$value->setValue($defaultValue);
}
}
}