zendframework / zend-inputfilter

InputFilter component from Zend Framework
BSD 3-Clause "New" or "Revised" License
64 stars 50 forks source link

Input with filter inside construct #8

Closed fabioginzel closed 9 years ago

fabioginzel commented 9 years ago

In my code i have input construct code:

use Zend\InputFilter\Input;

class Senha extends Input {

public function __construct() {
    parent::__construct('senha');
    $this->setRequired(true);
    $this->getFilterChain()->attachByName('StringTrim')
                           ->attachByName('StringToUpper')
                           ->attachByName('PandoraBase\Filter\Md5');
}       

}

in pull: https://github.com/zendframework/zend-inputfilter/pull/2

this break, because factory overwrite filters

manuakasam commented 9 years ago

Nothing should overwrite if you do $senha = new Senha()

If however you use the PluginManager to get your Filter, then you should be overwriting the init() function instead of the __construct(), just like you'd do with Forms. That way stuff will work as anticipated. Using the __construct() is always a bit tricky if there's a manager wrapped around, as most people rely on the manager to initialize some defaults.

fabioginzel commented 9 years ago

in my login input filter i do this: class Login extends InputFilter{

public function init() {

    $this->add(array(
            'name'     => 'cpf',
            'required' => true,
            'filters'  => array(
                    array('name' =>'Digits')
            ),
    ));

    $this->add(array(
            'type'=> 'Application\Filter\Senha'
    ),'senha'); 

}       

and Login not call init method of senha filter

manuakasam commented 9 years ago

Still too early in the morning. Could you try adding the Zend\Stdlib\InitializableInterface to your Filter? And then define the init function obviously? If not I'm just really on a wrong track here, sorry should that turn out to be the case!

Fabio Ginzel notifications@github.com schrieb am Mi., 29. Juli 2015 um 08:18 Uhr:

in my login input filter i do this: class Login extends InputFilter{

public function init() {

$this->add(array(
        'name'     => 'cpf',
        'required' => true,
        'filters'  => array(
                array('name' =>'Digits')
        ),
));

$this->add(array(
        'type'=> 'Application\Filter\Senha'
),'senha');

}

and Login not call init method of senha filter

— Reply to this email directly or view it on GitHub https://github.com/zendframework/zend-inputfilter/issues/8#issuecomment-125853789 .

fabioginzel commented 9 years ago

With InitializableInterface it calls init, but in the line 202 of Zend\InputFilter\Factory it overwrites filterchain:

    if ($this->defaultFilterChain) {
        $input->setFilterChain(clone $this->defaultFilterChain);
    }
weierophinney commented 9 years ago

@fabioginzel You have two choices:

You have to choose which approach you want. We cannot support both simultaneously.

Since you seem concerned with being able to attach custom filters, you have two possible approaches.

First, make sure they're registered in the filter plugin factory. If they are, then you can attach them during init() without a problem; the filter chain will be aware of them.

Alternately, override setFilterChain() such that it adds the filters when the filter chain is injected:

public function setFilterChain(FilterChain $chain)
{
    $chain->attachByName('StringTrim'); // etc.
    return parent::setFilterChain($chain);
}

Each of the approaches listed above are viable with the current code base.

weierophinney commented 9 years ago

in pull:

2

this break, because factory overwrite filters

BTW, I'm totally not seeing how you came to this conclusion. That patch does not touch any code that would inject the filter chain or validator chain in the least; all it does is allow you to specify the class to use when instantiating an input.

fabioginzel commented 9 years ago

@weierophinney

In my tests Init() is called before factory inject filter chain, overwriting my filters

Before patch in this line: if ($this->getInputFilterManager()->has($class)) { return $this->createInputFilter($inputSpecification); }

its return input and not inject default filter chain

ckappelhoff commented 7 years ago

@weierophinney, I can confirm, what @fabioginzel wrote: The init() method will be called, when the input will be fetched from the InputFilterManager, which is done here: https://github.com/zendframework/zend-inputfilter/blob/release-2.7.4/src/Factory.php#L169

The InputFilterChain will then be overwritten some lines below: https://github.com/zendframework/zend-inputfilter/blob/release-2.7.4/src/Factory.php#L193

The only work around I see is, to prevent setting a filter chain via the setter:

public function __construct($name = null)
{
    parent::__construct($name);
    $this->filterChain = new FilterChain();
}

public function setFilterChain(FilterChain $filterChain)
{

}

... kind of ugly.