cgsmith / zf1-recaptcha-2

Zend Framework 1 integration for Google reCAPTCHA version 2.0
MIT License
9 stars 11 forks source link

Doesn't work with sub-forms #7

Open maartentibau opened 8 years ago

maartentibau commented 8 years ago

Hi,

Really nice that you made this! But when you work with sub-forms in ZF, the script doesn't work anymore. That's because Google generates it's own code for the input field (textarea) and that's always the POST param "g-recaptcha-response".

So when working with sub-forms you never retrieve the value of that field. I made a work-around by retrieving the raw request params and than perform a verify with the API (the same code that you use in the _verify method).

But just wanted to let you know this.. if you would find a more suitable solution that would be great of course.. I'll try myself, if I find something, I'll let you know!

cgsmith commented 8 years ago

Thanks for reporting this! Do you have a simple sub-form gist you can post so I can test it out? Maybe myself or @elightbo can help out on this.

maartentibau commented 8 years ago

It's pretty simple. When you create a sub-form with the name "example" .. the name of that input field becomes this:

<input id="example-g-recaptcha-response" name="example[g-recaptcha-response]" />

Now the javascript code of Goolge re-renders the input field to this

<textarea class="g-recaptcha-response" name="g-recaptcha-response" id="g-recaptcha-response"></textarea>

So.. as you can see, when you submit the form, the validation will always fail. I searched if it was possible to alter the name that ReCaptcha generates, but that isn't possible as far as I know.

Anyhow.. to make it all work I do this

... generate the form ...

//get the sub-form element
$elReCaptcha = $form->getSubForm('example')->getElement('g-recaptcha-response');

//when the a post request is being submit before we first retrieve the recaptcha param
if ($this->_request->isPost()) {
    $reCaptcha = (string) $this->_request->getParam('g-recaptcha-response');

    //now we verify the recaptcha (same code used as in the _verify in the recaptcha validator) if the
    //validation is successful we remove the validator from the element so it won't block the overall
    //validation of the form
    if (!empty($reCaptcha) && ReCaptcha::verify($reCaptcha)) {
        $elReCaptcha->removeValidator('ReCaptcha');
        $elReCaptcha->setAllowEmpty(true);
    }

    if ($form->isValid($this->_request->getParams())) {
        .....

        $form->reset();

        //at the end we need to add the recaptcha validator
        $elReCaptcha->addValidator('ReCaptcha');
        $elReCaptcha->setAllowEmpty(false);
    }
}

Anyhow.. I don't know if it's possible.. but of course it would be cool if there would be a solid solution for this.