File indexing completed on 2025-03-02 05:29:25
0001 <?php 0002 /** 0003 * Zend Framework 0004 * 0005 * LICENSE 0006 * 0007 * This source file is subject to the new BSD license that is bundled 0008 * with this package in the file LICENSE.txt. 0009 * It is also available through the world-wide-web at this URL: 0010 * http://framework.zend.com/license/new-bsd 0011 * If you did not receive a copy of the license and are unable to 0012 * obtain it through the world-wide-web, please send an email 0013 * to license@zend.com so we can send you a copy immediately. 0014 * 0015 * @category Zend 0016 * @package Zend_Form 0017 * @subpackage Element 0018 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0019 * @license http://framework.zend.com/license/new-bsd New BSD License 0020 * @version $Id$ 0021 */ 0022 0023 /** @see Zend_Form_Element_Xhtml */ 0024 // require_once 'Zend/Form/Element/Xhtml.php'; 0025 0026 /** @see Zend_Captcha_Adapter */ 0027 // require_once 'Zend/Captcha/Adapter.php'; 0028 0029 /** 0030 * Generic captcha element 0031 * 0032 * This element allows to insert CAPTCHA into the form in order 0033 * to validate that human is submitting the form. The actual 0034 * logic is contained in the captcha adapter. 0035 * 0036 * @see http://en.wikipedia.org/wiki/Captcha 0037 * 0038 * @category Zend 0039 * @package Zend_Form 0040 * @subpackage Element 0041 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0042 * @license http://framework.zend.com/license/new-bsd New BSD License 0043 */ 0044 class Zend_Form_Element_Captcha extends Zend_Form_Element_Xhtml 0045 { 0046 /** 0047 * Captcha plugin type constant 0048 */ 0049 const CAPTCHA = 'CAPTCHA'; 0050 0051 /** 0052 * Captcha adapter 0053 * 0054 * @var Zend_Captcha_Adapter 0055 */ 0056 protected $_captcha; 0057 0058 /** 0059 * Get captcha adapter 0060 * 0061 * @return Zend_Captcha_Adapter 0062 */ 0063 public function getCaptcha() 0064 { 0065 return $this->_captcha; 0066 } 0067 0068 /** 0069 * Set captcha adapter 0070 * 0071 * @param string|array|Zend_Captcha_Adapter $captcha 0072 * @param array $options 0073 */ 0074 public function setCaptcha($captcha, $options = array()) 0075 { 0076 if ($captcha instanceof Zend_Captcha_Adapter) { 0077 $instance = $captcha; 0078 } else { 0079 if (is_array($captcha)) { 0080 if (array_key_exists('captcha', $captcha)) { 0081 $name = $captcha['captcha']; 0082 unset($captcha['captcha']); 0083 } else { 0084 $name = array_shift($captcha); 0085 } 0086 $options = array_merge($options, $captcha); 0087 } else { 0088 $name = $captcha; 0089 } 0090 0091 $name = $this->getPluginLoader(self::CAPTCHA)->load($name); 0092 if (empty($options)) { 0093 $instance = new $name; 0094 } else { 0095 $r = new ReflectionClass($name); 0096 if ($r->hasMethod('__construct')) { 0097 $instance = $r->newInstanceArgs(array($options)); 0098 } else { 0099 $instance = $r->newInstance(); 0100 } 0101 } 0102 } 0103 0104 $this->_captcha = $instance; 0105 $this->_captcha->setName($this->getName()); 0106 return $this; 0107 } 0108 0109 /** 0110 * Constructor 0111 * 0112 * $spec may be: 0113 * - string: name of element 0114 * - array: options with which to configure element 0115 * - Zend_Config: Zend_Config with options for configuring element 0116 * 0117 * @param string|array|Zend_Config $spec 0118 * @return void 0119 */ 0120 public function __construct($spec, $options = null) 0121 { 0122 parent::__construct($spec, $options); 0123 $this->setAllowEmpty(true) 0124 ->setRequired(true) 0125 ->setAutoInsertNotEmptyValidator(false) 0126 ->addValidator($this->getCaptcha(), true); 0127 } 0128 0129 /** 0130 * Set options 0131 * 0132 * Overrides to allow passing captcha options 0133 * 0134 * @param array $options 0135 * @return Zend_Form_Element_Captcha 0136 */ 0137 public function setOptions(array $options) 0138 { 0139 $captcha = null; 0140 $captchaOptions = array(); 0141 0142 if (array_key_exists('captcha', $options)) { 0143 $captcha = $options['captcha']; 0144 if (array_key_exists('captchaOptions', $options)) { 0145 $captchaOptions = $options['captchaOptions']; 0146 unset($options['captchaOptions']); 0147 } 0148 unset($options['captcha']); 0149 } 0150 parent::setOptions($options); 0151 0152 if(null !== $captcha) { 0153 $this->setCaptcha($captcha, $captchaOptions); 0154 } 0155 return $this; 0156 } 0157 0158 /** 0159 * Render form element 0160 * 0161 * @param Zend_View_Interface $view 0162 * @return string 0163 */ 0164 public function render(Zend_View_Interface $view = null) 0165 { 0166 $captcha = $this->getCaptcha(); 0167 $captcha->setName($this->getFullyQualifiedName()); 0168 0169 if (!$this->loadDefaultDecoratorsIsDisabled()) { 0170 $decorators = $this->getDecorators(); 0171 $decorator = $captcha->getDecorator(); 0172 $key = get_class($this->_getDecorator($decorator, null)); 0173 0174 if (!empty($decorator) && !array_key_exists($key, $decorators)) { 0175 array_unshift($decorators, $decorator); 0176 } 0177 0178 $decorator = array('Captcha', array('captcha' => $captcha)); 0179 $key = get_class($this->_getDecorator($decorator[0], $decorator[1])); 0180 0181 if ($captcha instanceof Zend_Captcha_Word && !array_key_exists($key, $decorators)) { 0182 array_unshift($decorators, $decorator); 0183 } 0184 0185 $this->setDecorators($decorators); 0186 } 0187 0188 $this->setValue($this->getCaptcha()->generate()); 0189 0190 return parent::render($view); 0191 } 0192 0193 /** 0194 * Retrieve plugin loader for validator or filter chain 0195 * 0196 * Support for plugin loader for Captcha adapters 0197 * 0198 * @param string $type 0199 * @return Zend_Loader_PluginLoader 0200 * @throws Zend_Loader_Exception on invalid type. 0201 */ 0202 public function getPluginLoader($type) 0203 { 0204 $type = strtoupper($type); 0205 if ($type == self::CAPTCHA) { 0206 if (!isset($this->_loaders[$type])) { 0207 // require_once 'Zend/Loader/PluginLoader.php'; 0208 $this->_loaders[$type] = new Zend_Loader_PluginLoader( 0209 array('Zend_Captcha' => 'Zend/Captcha/') 0210 ); 0211 } 0212 return $this->_loaders[$type]; 0213 } else { 0214 return parent::getPluginLoader($type); 0215 } 0216 } 0217 0218 /** 0219 * Add prefix path for plugin loader for captcha adapters 0220 * 0221 * This method handles the captcha type, the rest is handled by 0222 * the parent 0223 * @param string $prefix 0224 * @param string $path 0225 * @param string $type 0226 * @return Zend_Form_Element 0227 * @see Zend_Form_Element::addPrefixPath 0228 */ 0229 public function addPrefixPath($prefix, $path, $type = null) 0230 { 0231 $type = strtoupper($type); 0232 switch ($type) { 0233 case null: 0234 $loader = $this->getPluginLoader(self::CAPTCHA); 0235 $nsSeparator = (false !== strpos($prefix, '\\'))?'\\':'_'; 0236 $cPrefix = rtrim($prefix, $nsSeparator) . $nsSeparator . 'Captcha'; 0237 $cPath = rtrim($path, '/\\') . '/Captcha'; 0238 $loader->addPrefixPath($cPrefix, $cPath); 0239 return parent::addPrefixPath($prefix, $path); 0240 case self::CAPTCHA: 0241 $loader = $this->getPluginLoader($type); 0242 $loader->addPrefixPath($prefix, $path); 0243 return $this; 0244 default: 0245 return parent::addPrefixPath($prefix, $path, $type); 0246 } 0247 } 0248 0249 /** 0250 * Load default decorators 0251 * 0252 * @return Zend_Form_Element_Captcha 0253 */ 0254 public function loadDefaultDecorators() 0255 { 0256 if ($this->loadDefaultDecoratorsIsDisabled()) { 0257 return $this; 0258 } 0259 0260 $decorators = $this->getDecorators(); 0261 if (empty($decorators)) { 0262 $this->addDecorator('Errors') 0263 ->addDecorator('Description', array('tag' => 'p', 'class' => 'description')) 0264 ->addDecorator('HtmlTag', array('tag' => 'dd', 'id' => $this->getName() . '-element')) 0265 ->addDecorator('Label', array('tag' => 'dt')); 0266 } 0267 return $this; 0268 } 0269 0270 /** 0271 * Is the captcha valid? 0272 * 0273 * @param mixed $value 0274 * @param mixed $context 0275 * @return boolean 0276 */ 0277 public function isValid($value, $context = null) 0278 { 0279 $this->getCaptcha()->setName($this->getName()); 0280 $belongsTo = $this->getBelongsTo(); 0281 if (empty($belongsTo) || !is_array($context)) { 0282 return parent::isValid($value, $context); 0283 } 0284 0285 $name = $this->getFullyQualifiedName(); 0286 $root = substr($name, 0, strpos($name, '[')); 0287 $segments = substr($name, strpos($name, '[')); 0288 $segments = ltrim($segments, '['); 0289 $segments = rtrim($segments, ']'); 0290 $segments = explode('][', $segments); 0291 array_unshift($segments, $root); 0292 array_pop($segments); 0293 $newContext = $context; 0294 foreach ($segments as $segment) { 0295 if (array_key_exists($segment, $newContext)) { 0296 $newContext = $newContext[$segment]; 0297 } 0298 } 0299 0300 return parent::isValid($value, $newContext); 0301 } 0302 }