public function buildForm(FormBuilderInterface $builder, array $options) { $builder->add('name', TextType::class, ['label' => 'Display name - this will be displayed as the text of the generated link']); $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) { /** @var MenuItem $item */ $item = $event->getData(); $route = $item->getRoute(); $routeParameters = []; /** @var MenuItemParameter $parameter */ foreach ($item->getParameters() as $parameter) { $routeParameter = $parameter->getParameter(); $routeParameters[$routeParameter->getId()] = $routeParameter; } /** @var RouteParameter $parameter */ foreach ($route->getParameters() as $parameter) { if (isset($routeParameters[$parameter->getId()])) { continue; } // Add missing required parameters if ($parameter->getType()->getId() == RouteParameterType::ID_REQUIRED) { $menuParameter = new MenuItemParameter(); $menuParameter->setParameter($parameter); $menuParameter->setItem($item); $item->addParameter($menuParameter); } } }); $builder->addEventListener(FormEvents::POST_SET_DATA, function (FormEvent $event) use($builder) { $duplicateValidator = function ($object, ExecutionContextInterface $context) use($builder) { // this constraint has to be moved to this form's options // then set its error path to properties /** @var MenuItem $item */ $item = $builder->getData(); $duplicates = []; /** @var MenuItemParameter $menuParameter */ foreach ($item->getParameters() as $menuParameter) { $parameter = $menuParameter->getParameter(); $key = $item->getId() . '_' . $parameter->getId(); if (isset($duplicates[$key])) { $context->buildViolation('A duplicate entry for Parameter "' . $parameter->getParameter() . '" was found')->addViolation(); } $duplicates[$key] = true; } }; $requiredValidator = function ($object, ExecutionContextInterface $context) use($builder) { // this constraint has to be moved to this form's options // then set its error path to properties /** @var MenuItem $item */ $item = $builder->getData(); $route = $item->getRoute(); $required = []; /** @var RouteParameter $parameter */ foreach ($route->getParameters() as $parameter) { if ($parameter->getType()->getId() == RouteParameterType::ID_REQUIRED) { $required[$parameter->getId()] = $parameter; } } /** @var MenuItemParameter $menuParameter */ foreach ($item->getParameters() as $menuParameter) { $parameter = $menuParameter->getParameter(); unset($required[$parameter->getId()]); } /** @var RouteParameter $parameter */ foreach ($required as $parameter) { $context->buildViolation('The Required Parameter "' . $parameter->getParameter() . '" is missing')->addViolation(); } }; $form = $event->getForm(); /** @var MenuItem $item */ $item = $event->getData(); $form->add('parameters', CollectionType::class, ['label' => 'URL Parameters', 'entry_type' => MenuItemParameterType::class, 'entry_options' => ['item' => $item], 'constraints' => [new Callback(['callback' => $duplicateValidator]), new Callback(['callback' => $requiredValidator])]]); // $route = $item->getRoute(); // /** @var RouteParameter $parameter */ // foreach ($route->getParameters() as $parameter) { // if ('_locale' == $parameter->getParameter()) { // $form->add('useCurrentLocale', CheckboxType::class, [ // 'label' => 'Use the current locale if available' // ]); // break; // } // } }); $builder->addEventListener(FormEvents::POST_SUBMIT, function (FormEvent $event) { /** @var MenuItem $item */ $item = $event->getData(); /** @var MenuItemParameter $menuParameter */ foreach ($item->getParameters() as $menuParameter) { $menuParameter->setItem($item); // is this still needed? Maybe if we add some dynamically } }); }