<?php
namespace App\Form;
use App\Service\JsonFormManager;
use App\Service\ProcessFormService;
use Exception;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Exception\InvalidConfigurationException;
use Symfony\Component\Form\Form;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\Constraints as Assert;
class JsonType extends AbstractType
{
/** @var ProcessFormService $processFormService */
private $processFormService;
/**
* @param ProcessFormService $processFormService
*/
public function __construct(ProcessFormService $processFormService)
{
$this->processFormService = $processFormService;
}
/**
* @param FormBuilderInterface $builder
* @param array $options
* @return void
* @throws Exception
*/
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$manager = $options['manager'];
$formLead = $options['form_lead'];
if (!$manager instanceof JsonFormManager) {
throw new InvalidConfigurationException;
}
foreach ($manager->getFormDefinition() as $formGroup) {
$formGroup['options']['attr'] = $formGroup['attr'];
$groupItem = $builder->create(
$formGroup['name'],
$formGroup['class'],
$formGroup['options']
);
foreach ($formGroup['fields'] as $field) {
$groupItem->add(
$field['name'],
$field['class'],
$this->processFormService->buildOptions($field, $formLead)
);
}
$builder->add($groupItem);
}
$builder->addEventListener(FormEvents::PRE_SUBMIT, [$this, 'onPreSubmit']);
}
/**
* @param OptionsResolver $resolver
* @return void
*/
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'manager' => null,
'form_lead' => null,
'csrf_protection' => false
]);
}
/**
* @param FormEvent $event
* @return void
*/
public function onPreSubmit(FormEvent $event): void
{
/** @var Form $form */
$form = $event->getForm();
$data = $event->getData();
foreach ($form->all() as $group) {
/** @var Form $child */
foreach ($group as $child) {
$childName = $child->getName();
$type = get_class($child->getConfig()->getType()->getInnerType());
$options = $child->getConfig()->getOptions();
foreach ($options['attr'] as $key => $attr) {
if (strpos($key, 'incompatible-with') === false) {
continue;
}
$incompatibleName = $this->processFormService->getExplodedIncompatibleField($attr);
$groupName = $incompatibleName[0];
$incompatibleFieldName = JsonFormManager::buildFieldName($incompatibleName[1], $incompatibleName[2]);
$incompatibleField = $form->get($groupName)->get($incompatibleFieldName);
$incompatibleGroupLabel = $form->get($groupName)->getConfig()->getOption('label');
$incompatibleFieldLabel = $incompatibleField->getConfig()->getOption('label');
$notEqualOptions = [
'value' => $data[$groupName][$incompatibleFieldName]
];
$message = 'Este valor debe ser distinto al de ';
if ($incompatibleFieldLabel) {
$message .= $incompatibleFieldLabel;
$notEqualOptions['message'] = $message;
}
if ($incompatibleGroupLabel) {
$message .= " (Grupo: $incompatibleGroupLabel)";
$notEqualOptions['message'] = $message;
}
$options['constraints'] = new Assert\NotEqualTo($notEqualOptions);
$group->add($childName, $type, $options);
}
}
}
}
}