instantiation of validator plugin manager?

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

instantiation of validator plugin manager?

Oliver Koenig
This post has NOT been accepted by the mailing list yet.
Hi,

I was trying to override a default validator and stumbled upon sometzhing I found weird.
Each instance of Zend\InputFilter\Input instantiates its own instance of Zend\Validator\ValidatorChain.
Each instance of Zend\Validator\ValidatorChain instantiates its own instance of Zend\Validator\ValidatorPluginManager.
So that means in effect, every input field with a validator instantiates a new ValidatorPluginManager.
Is this behaviour supposed to be desirable?

The reason why I was in need to override the behaviour of a default validator: I use FilePRG and get the ATTACK error message from the validator, because the file is not in the HTTP POST after FilePRG.
I use factory backed form creation, it's not an option to switch to code based form creation.
So even if I tell my form element to use the 'fileuploadfile' validator, I can't override it with a modified version.
If I don't set it in the form element validators, I can override Zend\InputFilter\FileInput (which I do), but then how do I inject the validator in the validator chain? I don't want to instantiate a new validator for every field, because it doesn't need to, it can be a service, which needs only one instance.

Regards,
Oliver
Reply | Threaded
Open this post in threaded view
|

Re: instantiation of validator plugin manager?

Oliver Koenig
This post has NOT been accepted by the mailing list yet.
Hi,

a halfway workaround:
1. Derive from Zend\InputFilter\FileInput and override injectUploadValidator();
2. Zend\Validator\File\UploadFile and override isValid().
3. Derive from Zend\Form\Element\File and override getInputSpecification().

The problem now is how to check in the validator if the file was uploaded or not.
I use FilePRG with FileRenameUpload, so the uploaded file is moved to my temporary upload directory which I specify in the options for FileRenameUpload.
How can the validator know about where the temporary file is allowed to come from?
I can't pass it options, because I can't define it in the factory form spec, otherwise it would be set with the standard version of Zend\Validator\File\UploadFile which has the undesired behaviour.

If I could somehow prime the ValidatorChain with a ValidatorPluginManager, but the ValidatorChain is instantiated in Zend\InputFilter\Input, which is the parent class of FileInput.

I'm using my own version of FormFactory, so I don't know if the FormAbstractServiceFactory could help me in any way.

The obvious quick & dirty workaround would be to set a global upload directory, I guess it's the only way out for now.

Any ideas?

 

On 2014-06-14 17:38, Oliver Koenig [via Zend Framework Community] wrote:
Hi,

I was trying to override a default validator and stumbled upon sometzhing I found weird.
Each instance of Zend\InputFilter\Input instantiates its own instance of Zend\Validator\ValidatorChain.
Each instance of Zend\Validator\ValidatorChain instantiates its own instance of Zend\Validator\ValidatorPluginManager.
So that means in effect, every input field with a validator instantiates a new ValidatorPluginManager.
Is this behaviour supposed to be desirable?

The reason why I was in need to override the behaviour of a default validator: I use FilePRG and get the ATTACK error message from the validator, because the file is not in the HTTP POST after FilePRG.
I use factory backed form creation, it's not an option to switch to code based form creation.
So even if I tell my form element to use the 'fileuploadfile' validator, I can't override it with a modified version.
If I don't set it in the form element validators, I can override Zend\InputFilter\FileInput (which I do), but then how do I inject the validator in the validator chain? I don't want to instantiate a new validator for every field, because it doesn't need to, it can be a service, which needs only one instance.

Regards,
Oliver


If you reply to this email, your message will be added to the discussion below:
http://zend-framework-community.634137.n4.nabble.com/instantiation-of-validator-plugin-manager-tp4662142.html
To start a new topic under Zend Framework, email [hidden email]
To unsubscribe from Zend Framework Community, click here.
NAML

Reply | Threaded
Open this post in threaded view
|

Re: instantiation of validator plugin manager?

Marco Pivetta
In reply to this post by Oliver Koenig
On 14 June 2014 17:28, Oliver Koenig [via Zend Framework Community] <[hidden email]> wrote:
Hi,

I was trying to override a default validator and stumbled upon sometzhing I found weird.
Each instance of Zend\InputFilter\Input instantiates its own instance of Zend\Validator\ValidatorChain.
Each instance of Zend\Validator\ValidatorChain instantiates its own instance of Zend\Validator\ValidatorPluginManager.

That should only be the case if the input filter was not built through the InputFilterPluginManager. Can you verify that?
 
So that means in effect, every input field with a validator instantiates a new ValidatorPluginManager.

Also here, only if the form didn't spawn from the FormElementManager
 
Is this behaviour supposed to be desirable?

No, but the alternate solution is having a static reference to a plugin manager, which is much worse.
 

The reason why I was in need to override the behaviour of a default validator: I use FilePRG and get the ATTACK error message from the validator, because the file is not in the HTTP POST after FilePRG.
I use factory backed form creation, it's not an option to switch to code based form creation.

I'd check if you can use the FormElementManager coming from the main ServiceManager instance to build your forms (or a form factory).

Reply | Threaded
Open this post in threaded view
|

Re: instantiation of validator plugin manager?

Oliver Koenig
This post has NOT been accepted by the mailing list yet.
Hi Marco,

thanks!
I'm using a custom Form Factory, derived from Zend\Form\Factory, to create the forms.
My next idea would be to implement in my Form Factory a method to inject my derived ValidatorChain into all InputFilter's of all Elements, and create a ValidatorChainFactory service to be injected in my Form Factory. Then I would derive the ValidatorChain and the ValidatorPluginManager, the latter I would have constructed as service in service manager.

Thanks & regards,
Oliver

On 2014-06-15 12:35, Marco Pivetta [via Zend Framework Community] wrote:
On 14 June 2014 17:28, Oliver Koenig [via Zend Framework Community] <[hidden email]> wrote:
Hi,

I was trying to override a default validator and stumbled upon sometzhing I found weird.
Each instance of Zend\InputFilter\Input instantiates its own instance of Zend\Validator\ValidatorChain.
Each instance of Zend\Validator\ValidatorChain instantiates its own instance of Zend\Validator\ValidatorPluginManager.

That should only be the case if the input filter was not built through the InputFilterPluginManager. Can you verify that?
 
So that means in effect, every input field with a validator instantiates a new ValidatorPluginManager.

Also here, only if the form didn't spawn from the FormElementManager
 
Is this behaviour supposed to be desirable?

No, but the alternate solution is having a static reference to a plugin manager, which is much worse.
 

The reason why I was in need to override the behaviour of a default validator: I use FilePRG and get the ATTACK error message from the validator, because the file is not in the HTTP POST after FilePRG.
I use factory backed form creation, it's not an option to switch to code based form creation.

I'd check if you can use the FormElementManager coming from the main ServiceManager instance to build your forms (or a form factory).




If you reply to this email, your message will be added to the discussion below:
http://zend-framework-community.634137.n4.nabble.com/instantiation-of-validator-plugin-manager-tp4662142p4662145.html
To start a new topic under Zend Framework, email [hidden email]
To unsubscribe from instantiation of validator plugin manager?, click here.
NAML

Reply | Threaded
Open this post in threaded view
|

Re: instantiation of validator plugin manager?

Oliver Koenig
This post has NOT been accepted by the mailing list yet.
In reply to this post by Marco Pivetta
Solved it. Here's what I did, for reference, in case it might help anyone.

instantiate ValidatorPluginManager as service in service manager and add the validators invokables defined in config to it:
(not elegant, couldn't figure out the "proper" ZF2 way to do it, eventually gave up and went the path of least resistance)

            'ValidatorPluginManager' => function(
                ServiceLocatorInterface $serviceLocator
            ) {
                $service = new Zend\Validator\ValidatorPluginManager();
                $validators = $serviceLocator->get('ConfigAccessor')->get('validators\invokables');
                foreach ($validators as $name => $class) {
                    $service->setInvokableClass($name, $class);
                }
                return $service;
            },

define a custom validator in config, derived from Zend\Validator\File\UploadFile:

    'validators' => [
        'invokables' => [
            'Xapp/File/UploadFile' => 'Xapp\Validator\File\UploadFile',
        ],
    ],

derive Form Factory: override getInputFilterFactory() to inject the ValidatorPluginManager into the default ValidatorChain:

    public function getInputFilterFactory()
    {
        if (null === $this->inputFilterFactory) {
            $inputFilterFactory = new InputFilterFactory();
            $inputFilterFactory->getDefaultValidatorChain()->setPluginManager(
                $this->getValidatorPluginManager()
            );
            $this->setInputFilterFactory($inputFilterFactory);
        }
        return $this->inputFilterFactory;
    }

in form spec, pass the tmp upload dir as an option to the validator:

                    'validators' => [
                        ['name' => 'Xapp/File/UploadFile', 'options' => [
                            'upload-dir' => './data/tmpuploads/',
                        ]],
                    ],
                    'filters' => [
                        ['name' => 'File/RenameUpload', 'options' => [
                            'target' => './data/tmpuploads/',
                            'randomize' => true,
                        ]],
                    ],

in the custom validator (derived from Zend\Validator\File\UploadFile), compare uploaded file name with the tmp upload dir given in validator options:

    protected function isUploadedFile(
        $file
    ) {
        if (is_uploaded_file($file)) {
            return true;
        }
        $uploadDir = $this->getOption('upload-dir');
        if (XStringUtils::startsWith($file, $uploadDir)) {
            return true;
        }
        return false;
    }

...and override isValid() and change one line:
    (unfortunately have to copy the entire function to change the one line only)

            case UPLOAD_ERR_OK:
                // was: if (is_uploaded_file($file)) {
                if (!$this->isUploadedFile($file)) {
                    $this->error(self::ATTACK);
                }
                break;



On 2014-06-15 13:47, Oliver Koenig wrote:
Hi Marco,

thanks!
I'm using a custom Form Factory, derived from Zend\Form\Factory, to create the forms.
My next idea would be to implement in my Form Factory a method to inject my derived ValidatorChain into all InputFilter's of all Elements, and create a ValidatorChainFactory service to be injected in my Form Factory. Then I would derive the ValidatorChain and the ValidatorPluginManager, the latter I would have constructed as service in service manager.

Thanks & regards,
Oliver

On 2014-06-15 12:35, Marco Pivetta [via Zend Framework Community] wrote:
On 14 June 2014 17:28, Oliver Koenig [via Zend Framework Community] <[hidden email]> wrote:
Hi,

I was trying to override a default validator and stumbled upon sometzhing I found weird.
Each instance of Zend\InputFilter\Input instantiates its own instance of Zend\Validator\ValidatorChain.
Each instance of Zend\Validator\ValidatorChain instantiates its own instance of Zend\Validator\ValidatorPluginManager.

That should only be the case if the input filter was not built through the InputFilterPluginManager. Can you verify that?
 
So that means in effect, every input field with a validator instantiates a new ValidatorPluginManager.

Also here, only if the form didn't spawn from the FormElementManager
 
Is this behaviour supposed to be desirable?

No, but the alternate solution is having a static reference to a plugin manager, which is much worse.
 

The reason why I was in need to override the behaviour of a default validator: I use FilePRG and get the ATTACK error message from the validator, because the file is not in the HTTP POST after FilePRG.
I use factory backed form creation, it's not an option to switch to code based form creation.

I'd check if you can use the FormElementManager coming from the main ServiceManager instance to build your forms (or a form factory).




If you reply to this email, your message will be added to the discussion below:
http://zend-framework-community.634137.n4.nabble.com/instantiation-of-validator-plugin-manager-tp4662142p4662145.html
To start a new topic under Zend Framework, email [hidden email]
To unsubscribe from instantiation of validator plugin manager?, click here.
NAML