web/enmi/Zend/Form/Element/Captcha.php
changeset 19 1c2f13fd785c
parent 0 4eba9c11703f
equal deleted inserted replaced
18:bd595ad770fc 19:1c2f13fd785c
       
     1 <?php
       
     2 /**
       
     3  * Zend Framework
       
     4  *
       
     5  * LICENSE
       
     6  *
       
     7  * This source file is subject to the new BSD license that is bundled
       
     8  * with this package in the file LICENSE.txt.
       
     9  * It is also available through the world-wide-web at this URL:
       
    10  * http://framework.zend.com/license/new-bsd
       
    11  * If you did not receive a copy of the license and are unable to
       
    12  * obtain it through the world-wide-web, please send an email
       
    13  * to license@zend.com so we can send you a copy immediately.
       
    14  *
       
    15  * @category   Zend
       
    16  * @package    Zend_Form
       
    17  * @subpackage Element
       
    18  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
       
    19  * @license    http://framework.zend.com/license/new-bsd     New BSD License
       
    20  * @version    $Id: Captcha.php 22328 2010-05-30 15:09:06Z bittarman $
       
    21  */
       
    22 
       
    23 /** @see Zend_Form_Element_Xhtml */
       
    24 require_once 'Zend/Form/Element/Xhtml.php';
       
    25 
       
    26 /** @see Zend_Captcha_Adapter */
       
    27 require_once 'Zend/Captcha/Adapter.php';
       
    28 
       
    29 /**
       
    30  * Generic captcha element
       
    31  *
       
    32  * This element allows to insert CAPTCHA into the form in order
       
    33  * to validate that human is submitting the form. The actual
       
    34  * logic is contained in the captcha adapter.
       
    35  *
       
    36  * @see http://en.wikipedia.org/wiki/Captcha
       
    37  *
       
    38  * @category   Zend
       
    39  * @package    Zend_Form
       
    40  * @subpackage Element
       
    41  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
       
    42  * @license    http://framework.zend.com/license/new-bsd     New BSD License
       
    43  */
       
    44 class Zend_Form_Element_Captcha extends Zend_Form_Element_Xhtml
       
    45 {
       
    46     /**
       
    47      * Captcha plugin type constant
       
    48      */
       
    49     const CAPTCHA = 'CAPTCHA';
       
    50 
       
    51     /**
       
    52      * Captcha adapter
       
    53      *
       
    54      * @var Zend_Captcha_Adapter
       
    55      */
       
    56     protected $_captcha;
       
    57 
       
    58     /**
       
    59      * Get captcha adapter
       
    60      *
       
    61      * @return Zend_Captcha_Adapter
       
    62      */
       
    63     public function getCaptcha()
       
    64     {
       
    65         return $this->_captcha;
       
    66     }
       
    67 
       
    68     /**
       
    69      * Set captcha adapter
       
    70      *
       
    71      * @param string|array|Zend_Captcha_Adapter $captcha
       
    72      * @param array $options
       
    73      */
       
    74     public function setCaptcha($captcha, $options = array())
       
    75     {
       
    76         if ($captcha instanceof Zend_Captcha_Adapter) {
       
    77             $instance = $captcha;
       
    78         } else {
       
    79             if (is_array($captcha)) {
       
    80                 if (array_key_exists('captcha', $captcha)) {
       
    81                     $name = $captcha['captcha'];
       
    82                     unset($captcha['captcha']);
       
    83                 } else {
       
    84                     $name = array_shift($captcha);
       
    85                 }
       
    86                 $options = array_merge($options, $captcha);
       
    87             } else {
       
    88                 $name = $captcha;
       
    89             }
       
    90 
       
    91             $name = $this->getPluginLoader(self::CAPTCHA)->load($name);
       
    92             if (empty($options)) {
       
    93                 $instance = new $name;
       
    94             } else {
       
    95                 $r = new ReflectionClass($name);
       
    96                 if ($r->hasMethod('__construct')) {
       
    97                     $instance = $r->newInstanceArgs(array($options));
       
    98                 } else {
       
    99                     $instance = $r->newInstance();
       
   100                 }
       
   101             }
       
   102         }
       
   103 
       
   104         $this->_captcha = $instance;
       
   105         $this->_captcha->setName($this->getName());
       
   106         return $this;
       
   107     }
       
   108 
       
   109     /**
       
   110      * Constructor
       
   111      *
       
   112      * $spec may be:
       
   113      * - string: name of element
       
   114      * - array: options with which to configure element
       
   115      * - Zend_Config: Zend_Config with options for configuring element
       
   116      *
       
   117      * @param  string|array|Zend_Config $spec
       
   118      * @return void
       
   119      */
       
   120     public function __construct($spec, $options = null)
       
   121     {
       
   122         parent::__construct($spec, $options);
       
   123         $this->setAllowEmpty(true)
       
   124              ->setRequired(true)
       
   125              ->setAutoInsertNotEmptyValidator(false)
       
   126              ->addValidator($this->getCaptcha(), true);
       
   127     }
       
   128 
       
   129     /**
       
   130      * Return all attributes
       
   131      *
       
   132      * @return array
       
   133      */
       
   134     public function getAttribs()
       
   135     {
       
   136         $attribs = get_object_vars($this);
       
   137         unset($attribs['helper']);
       
   138         foreach ($attribs as $key => $value) {
       
   139             if ('_' == substr($key, 0, 1)) {
       
   140                 unset($attribs[$key]);
       
   141             }
       
   142         }
       
   143 
       
   144         return $attribs;
       
   145     }
       
   146 
       
   147     /**
       
   148      * Set options
       
   149      *
       
   150      * Overrides to allow passing captcha options
       
   151      *
       
   152      * @param  array $options
       
   153      * @return Zend_Form_Element_Captcha
       
   154      */
       
   155     public function setOptions(array $options)
       
   156     {
       
   157         if (array_key_exists('captcha', $options)) {
       
   158             if (array_key_exists('captchaOptions', $options)) {
       
   159                 $this->setCaptcha($options['captcha'], $options['captchaOptions']);
       
   160                 unset($options['captchaOptions']);
       
   161             } else {
       
   162                 $this->setCaptcha($options['captcha']);
       
   163             }
       
   164             unset($options['captcha']);
       
   165         }
       
   166         parent::setOptions($options);
       
   167         return $this;
       
   168     }
       
   169 
       
   170     /**
       
   171      * Render form element
       
   172      *
       
   173      * @param  Zend_View_Interface $view
       
   174      * @return string
       
   175      */
       
   176     public function render(Zend_View_Interface $view = null)
       
   177     {
       
   178         $captcha    = $this->getCaptcha();
       
   179         $captcha->setName($this->getFullyQualifiedName());
       
   180 
       
   181         $decorators = $this->getDecorators();
       
   182 
       
   183         $decorator  = $captcha->getDecorator();
       
   184         if (!empty($decorator)) {
       
   185             array_unshift($decorators, $decorator);
       
   186         }
       
   187 
       
   188         $decorator = array('Captcha', array('captcha' => $captcha));
       
   189         array_unshift($decorators, $decorator);
       
   190 
       
   191         $this->setDecorators($decorators);
       
   192 
       
   193         $this->setValue($this->getCaptcha()->generate());
       
   194 
       
   195         return parent::render($view);
       
   196     }
       
   197 
       
   198     /**
       
   199      * Retrieve plugin loader for validator or filter chain
       
   200      *
       
   201      * Support for plugin loader for Captcha adapters
       
   202      *
       
   203      * @param  string $type
       
   204      * @return Zend_Loader_PluginLoader
       
   205      * @throws Zend_Loader_Exception on invalid type.
       
   206      */
       
   207     public function getPluginLoader($type)
       
   208     {
       
   209         $type = strtoupper($type);
       
   210         if ($type == self::CAPTCHA) {
       
   211             if (!isset($this->_loaders[$type])) {
       
   212                 require_once 'Zend/Loader/PluginLoader.php';
       
   213                 $this->_loaders[$type] = new Zend_Loader_PluginLoader(
       
   214                     array('Zend_Captcha' => 'Zend/Captcha/')
       
   215                 );
       
   216             }
       
   217             return $this->_loaders[$type];
       
   218         } else {
       
   219             return parent::getPluginLoader($type);
       
   220         }
       
   221     }
       
   222 
       
   223     /**
       
   224      * Add prefix path for plugin loader for captcha adapters
       
   225      *
       
   226      * This method handles the captcha type, the rest is handled by
       
   227      * the parent
       
   228      * @param  string $prefix
       
   229      * @param  string $path
       
   230      * @param  string $type
       
   231      * @return Zend_Form_Element
       
   232      * @see Zend_Form_Element::addPrefixPath
       
   233      */
       
   234     public function addPrefixPath($prefix, $path, $type = null)
       
   235     {
       
   236         $type = strtoupper($type);
       
   237         switch ($type) {
       
   238             case null:
       
   239                 $loader = $this->getPluginLoader(self::CAPTCHA);
       
   240                 $cPrefix = rtrim($prefix, '_') . '_Captcha';
       
   241                 $cPath   = rtrim($path, '/\\') . '/Captcha';
       
   242                 $loader->addPrefixPath($cPrefix, $cPath);
       
   243                 return parent::addPrefixPath($prefix, $path);
       
   244             case self::CAPTCHA:
       
   245                 $loader = $this->getPluginLoader($type);
       
   246                 $loader->addPrefixPath($prefix, $path);
       
   247                 return $this;
       
   248             default:
       
   249                 return parent::addPrefixPath($prefix, $path, $type);
       
   250         }
       
   251     }
       
   252 
       
   253     /**
       
   254      * Load default decorators
       
   255      *
       
   256      * @return void
       
   257      */
       
   258     public function loadDefaultDecorators()
       
   259     {
       
   260         if ($this->loadDefaultDecoratorsIsDisabled()) {
       
   261             return $this;
       
   262         }
       
   263 
       
   264         $decorators = $this->getDecorators();
       
   265         if (empty($decorators)) {
       
   266             $this->addDecorator('Errors')
       
   267                  ->addDecorator('Description', array('tag' => 'p', 'class' => 'description'))
       
   268                  ->addDecorator('HtmlTag', array('tag' => 'dd', 'id' => $this->getName() . '-element'))
       
   269                  ->addDecorator('Label', array('tag' => 'dt'));
       
   270         }
       
   271         return $this;
       
   272     }
       
   273 
       
   274     /**
       
   275      * Is the captcha valid?
       
   276      *
       
   277      * @param  mixed $value
       
   278      * @param  mixed $context
       
   279      * @return boolean
       
   280      */
       
   281     public function isValid($value, $context = null)
       
   282     {
       
   283         $this->getCaptcha()->setName($this->getName());
       
   284         $belongsTo = $this->getBelongsTo();
       
   285         if (empty($belongsTo) || !is_array($context)) {
       
   286             return parent::isValid($value, $context);
       
   287         }
       
   288 
       
   289         $name     = $this->getFullyQualifiedName();
       
   290         $root     = substr($name, 0, strpos($name, '['));
       
   291         $segments = substr($name, strpos($name, '['));
       
   292         $segments = ltrim($segments, '[');
       
   293         $segments = rtrim($segments, ']');
       
   294         $segments = explode('][', $segments);
       
   295         array_unshift($segments, $root);
       
   296         array_pop($segments);
       
   297         $newContext = $context;
       
   298         foreach ($segments as $segment) {
       
   299             if (array_key_exists($segment, $newContext)) {
       
   300                 $newContext = $newContext[$segment];
       
   301             }
       
   302         }
       
   303 
       
   304         return parent::isValid($value, $newContext);
       
   305     }
       
   306 }