1<?php 2/** 3 * Zend Framework (http://framework.zend.com/) 4 * 5 * @link http://github.com/zendframework/zf2 for the canonical source repository 6 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 7 * @license http://framework.zend.com/license/new-bsd New BSD License 8 */ 9 10namespace Zend\Form\View\Helper\Captcha; 11 12use Zend\Captcha\ReCaptcha as CaptchaAdapter; 13use Zend\Form\ElementInterface; 14use Zend\Form\Exception; 15use Zend\Form\View\Helper\FormInput; 16 17class ReCaptcha extends FormInput 18{ 19 /** 20 * Invoke helper as functor 21 * 22 * Proxies to {@link render()}. 23 * 24 * @param ElementInterface $element 25 * @return string 26 */ 27 public function __invoke(ElementInterface $element = null) 28 { 29 if (!$element) { 30 return $this; 31 } 32 33 return $this->render($element); 34 } 35 36 /** 37 * Render ReCaptcha form elements 38 * 39 * @param ElementInterface $element 40 * @throws Exception\DomainException 41 * @return string 42 */ 43 public function render(ElementInterface $element) 44 { 45 $attributes = $element->getAttributes(); 46 $captcha = $element->getCaptcha(); 47 48 if ($captcha === null || !$captcha instanceof CaptchaAdapter) { 49 throw new Exception\DomainException(sprintf( 50 '%s requires that the element has a "captcha" attribute implementing Zend\Captcha\AdapterInterface; none found', 51 __METHOD__ 52 )); 53 } 54 55 $name = $element->getName(); 56 $id = isset($attributes['id']) ? $attributes['id'] : $name; 57 $challengeName = empty($name) ? 'recaptcha_challenge_field' : $name . '[recaptcha_challenge_field]'; 58 $responseName = empty($name) ? 'recaptcha_response_field' : $name . '[recaptcha_response_field]'; 59 $challengeId = $id . '-challenge'; 60 $responseId = $id . '-response'; 61 62 $markup = $captcha->getService()->getHtml($name); 63 $hidden = $this->renderHiddenInput($challengeName, $challengeId, $responseName, $responseId); 64 $js = $this->renderJsEvents($challengeId, $responseId); 65 66 return $hidden . $markup . $js; 67 } 68 69 /** 70 * Render hidden input elements for the challenge and response 71 * 72 * @param string $challengeName 73 * @param string $challengeId 74 * @param string $responseName 75 * @param string $responseId 76 * @return string 77 */ 78 protected function renderHiddenInput($challengeName, $challengeId, $responseName, $responseId) 79 { 80 $pattern = '<input type="hidden" %s%s'; 81 $closingBracket = $this->getInlineClosingBracket(); 82 83 $attributes = $this->createAttributesString(array( 84 'name' => $challengeName, 85 'id' => $challengeId, 86 )); 87 $challenge = sprintf($pattern, $attributes, $closingBracket); 88 89 $attributes = $this->createAttributesString(array( 90 'name' => $responseName, 91 'id' => $responseId, 92 )); 93 $response = sprintf($pattern, $attributes, $closingBracket); 94 95 return $challenge . $response; 96 } 97 98 /** 99 * Create the JS events used to bind the challenge and response values to the submitted form. 100 * 101 * @param string $challengeId 102 * @param string $responseId 103 * @return string 104 */ 105 protected function renderJsEvents($challengeId, $responseId) 106 { 107 $elseif = 'else if'; // php-cs-fixer bug 108 $js =<<<EOJ 109<script type="text/javascript" language="JavaScript"> 110function windowOnLoad(fn) 111{ 112 var old = window.onload; 113 window.onload = function () { 114 if (old) { 115 old(); 116 } 117 fn(); 118 }; 119} 120function zendBindEvent(el, eventName, eventHandler) 121{ 122 if (el.addEventListener) { 123 el.addEventListener(eventName, eventHandler, false); 124 } $elseif (el.attachEvent) { 125 el.attachEvent('on'+eventName, eventHandler); 126 } 127} 128windowOnLoad(function () { 129 zendBindEvent( 130 document.getElementById("$challengeId").form, 131 'submit', 132 function (e) { 133 document.getElementById("$challengeId").value = document.getElementById("recaptcha_challenge_field").value; 134 document.getElementById("$responseId").value = document.getElementById("recaptcha_response_field").value; 135 } 136 ); 137}); 138</script> 139EOJ; 140 return $js; 141 } 142} 143