Необязательный входной фильтр коллекции - не проходит пустая / необязательная проверка - PullRequest
0 голосов
/ 13 июля 2020

У меня довольно сложная форма, которая представлена ​​в виде вкладок. Любой из наборов полей в форме должен быть заполнен, поэтому я ищу возможность использования OptionalInputFilter. Набор полей, с которым у меня проблема, представляет собой коллекцию. Я настроил входной фильтр для работы с коллекцией нормально, но дополнительный аспект, похоже, не работает. Чтобы было ясно, желаемый эффект заключается в том, что пользователь может либо добавить коллекцию элементов, каждый из которых соответствует / подтвержден, либо пользователь оставляет его пустым, и он проходит проверку.

Рассматриваемый набор полей :

class EventFieldset extends Fieldset
{
    public function __construct($name = null, $options = [])
    {
        parent::__construct('Events', $options);
    }

    public function init()
    {
        $this->add([
            'name' => 'date',
            'type'  => Date::class,
            'options' => [
            'label' => 'Date',
            'label_attributes' => [
                'class' => 'col-form-label'
            ],
        ],
        'attributes' => [
            'class' => 'form-control ',
            'required' => true,
        ],
    ]);

    $this->add([
        'name' => 'description',
        'type'  => Textarea::class,
        'options' => [
            'label' => 'Description',
            'label_attributes' => [
                'column' => 'md-2',
                'class' => 'col-form-label'
            ],
        ],
        'attributes' => [
            'class' => 'form-control',
            'minlength' => '10',
            'required' => true,
        ],
    ]);

    $this->add([
        'name' => 'hours',
        'type'  => Text::class,
        'options' => [
            'label' => 'Hours',
            'label_attributes' => [
                'column' => 'md-2',
                'class' => 'col-form-label'
            ],
           'column' => 'md-10'
        ],
        'attributes' => [
            'class' => 'has-event-duration duration-only form-control'
        ],
    ]);

}

}

Входной фильтр для указанного выше набора полей:

class EventInputFilter extends OptionalInputFilter
{
public function init()
{
    parent::init();
    $this->add([
        'name' => 'date',
        'validators' => [
            [
                'name' => Date::class,
                'options' => [
                    'format' => 'Y-m-d',
                    'strict' => true,
                ]
            ],
        ],
        'filters' => [
            ['name' => StripTags::class],
            [
                'name' => DateTimeFormatter::class,
                'options' => [
                    'format' => 'Y-m-d'
                ]
            ]
        ]
    ]);

    $this->add([
        'name' => 'description',
        'required' => true,
        'validators' => [
            [
                'name' => StringLength::class,
                'options' => [
                    'min' => 5,
                    'max' => 25600
                ]
            ]
        ],
        'filters' => [
            ['name' => StripTags::class],
            ['name' => StringTrim::class]
        ]
    ]);

    $this->add([
        'name' => 'hours',
        'required' => true,
        'validators' => [
            ['name' => AlnumValidator::class],
        ],
        'filters' => [
            ['name' => StripTags::class],
            ['name' => Alnum::class]
        ]
    ]);

}

}

Обратите внимание, как он расширяет OptionalInputFilter.

Форма:

class MyForm extends Form
{
public function init()
{
    parent::init();
    //other elements / fieldsets removed for brevity
    $this->add([
        'name' => 'manualRecords',
        'type' => ManuallyEnteredRecordsFieldset::class,
    ]);

    $this->add([
        'type' => Csrf::class,
        'name' => 'csrf',
        'options' => [
            'csrf_options' => [
                'timeout' => 600,
            ],
        ],
    ]);

    $this->add([
        'name' => 'Submit',
        'type' => Submit::class,
        'options' => [
            'label' => 'Submit',
            'variant' => 'outline-primary'
        ],
        'attributes' => [
            'class' => 'btn btn-primary',
            'value' => 'Submit'
        ]
    ]);
}

}

class ManuallyEnteredRecordFieldset extends Fieldset
{
public function init()
{
    //other elements here - removed for brevity
    $this->add([
        'name' => 'Events',
        'type' => Collection::class,
        'options' => [
            'count' => 1,
            'allow_add' => true,
            'should_create_template' => true,
            'target_element' => [
                'type' => EventFieldset::class
            ],
        ]
    ]);

Наконец, в фабрику форм добавлен входной фильтр:

class MyFormFactory implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
    $form = new MyForm();
    $form->setInputFilter($this->getInputFilter($container->get('InputFilterManager')));
    return $form;
}

protected function getInputFilter(InputFilterPluginManager $inputFilterPluginManager) : InputFilter
{
    //other input filters applied - removed for brevity
    $eventInputFilter = $inputFilterPluginManager->get(EventInputFilter::class);

    $baseInputFilter = new InputFilter();

    $collectionInputFilter = new CollectionInputFilter();
    $collectionInputFilter->setInputFilter($eventInputFilter);
    $manualRecordInputFilter = new OptionalInputFilter();   //note - also an OptionalInputFilter
    $manualRecordInputFilter->add($collectionInputFilter, 'Events');
    $baseInputFilter->add($manualRecordInputFilter, 'manualRecords');

    return $baseInputFilter;
}

}

Когда я отправляю эту форму с имеющимися данными, даже с добавленными 1-> N строками коллекции, она проверяется нормально. Без каких-либо введенных данных (которые, как я ожидал, все же пройдут, поскольку он построен из дополнительного входного фильтра), я получаю следующие сообщения об ошибках входного фильтра:

["manualRecords"] => array(2) {
["Events"] => array(1) {
  [0] => array(3) {
    ["date"] => array(2) {
      ["isEmpty"] => string(36) "Value is required and can't be empty"
    }
    ["description"] => array(1) {
      ["isEmpty"] => string(36) "Value is required and can't be empty"
    }
    ["hours"] => array(1) {
      ["isEmpty"] => string(36) "Value is required and can't be empty"
    }
  }
}

Это не то, как должно быть поведение согласно: https://docs.laminas.dev/laminas-inputfilter/optional-input-filters/

...