Изменить entry_options в CollectionType на основе данных записи - PullRequest
0 голосов
/ 28 июня 2018

У меня есть форма Symfony с коллекцией. Пользователи могут добавлять или удалять пользователей из организации (просто для примера). Однако я хочу запретить людям удалять определенных пользователей из организации. Допустим, администраторов нельзя удалить, но их имя все еще можно изменить.

Вот что у меня сейчас есть:

class OrganisationType extends AbstractType {

    public function buildForm(FormBuilderInterface $builder, array $options) {
        $builder->add(
            'users',
            CollectionType::class,
            [
                'required' => FALSE,
                'entry_type' => UserType::class,
                'label' => 'Users',
                'show_legend' => FALSE,
                'entry_options' => [
                    'label_render' => FALSE,
                    'data_class' => User::class,
                ],
                'widget_add_btn' => ['label' => 'Add user'],
                'by_reference' => FALSE,
                'allow_add' => TRUE,
                'allow_delete' => TRUE,
                'prototype' => TRUE,
            ]
        );
    }
}

class UserType extends AbstractType {

    public function buildForm(FormBuilderInterface $builder, array $options) {
        $builder
            ->add(
                'name',
                TextType::class,
                ['required' => TRUE]
            )
            ->add(
                'email',
                TextType::class,
                ['required' => TRUE]
            );
    }
}

Я читал о событиях формы , но при попытке использовать события формы в моем UserType, похоже, нет способа изменить записи в коллекции:

$builder->addEventListener(
        FormEvents::POST_SET_DATA,
        function(FormEvent $event) {
            $user = $event->getData();
            $form = $event->getForm();

            if ($user->isAdmin()) {
                //maybe some logic here? But what?
            }
        }
)

Могу ли я изменить entry_options на основе данных записи?

1 Ответ

0 голосов
/ 29 июня 2018

Если я правильно понимаю, это можно сделать, прослушав события PRE_SUBMIT и POST_SUBMIT на вашем OrganisationType.

Я бы начал с запоминания идентификаторов пользователей на PRE_SUBMIT, а затем на POST_SUBMIT проверил существующую коллекцию с предыдущей. Примерно так:

<?php
class OrganisationType extends AbstractType {

    private $preSubmitAdminsIds = [];

    public function buildForm(FormBuilderInterface $builder, array $options) {
        // ....

        $adminIds = $this->preSubmitAdminsIds;

        $builder
        ->addEventListener('PRE_SUBMIT', function(FormEvent $event) use (&$adminIds){ // ! Note the reference pass
            $org = $event->getData();
            $users = $org->getUsers();

            foreach ($users as $u){
                if ($u->isAdmin()){
                    $adminIds[] = $u->getId(); // I guess you do have some sort of id
                }
            }
        })
        ->addEventListener('POST_SUBMIT', function(FormEvent $event) use (&$adminIds) { // ! Note the reference pass
            $org = $event->getData();
            $users = $org->getUsers();
            $newAdminIds = [];

            foreach ($users as $u){
                if ($u->isAdmin()){
                    $newAdminIds[] = $u->getId();
                }
            }

            if (!empty(array_diff($adminIds, $newAdminIds))){
                $event->getForm()->get('users')->addError("You cannot remove admins!");
            }
        });

        // ....
    }
} 

Пара заметок:

  1. У пользователя должен быть некоторый неизменный идентификатор (getId())
  2. Я бы, вероятно, отложил логику пост-отправки для валидатора, но я был бы очень похож на логику, описанную выше.
  3. Обратите внимание, что я передал ссылку adminIds анонимной функции. Если это кажется вам слишком грязным, вы можете на самом деле передать private ссылку на метод. Это также облегчает доступ к полям классов.
  4. При необходимости вы должны выполнить проверку нулевой безопасности для $org->getUsers() в зависимости от реализации вашей сущности ...

Надеюсь, это поможет ...

...