Thursday, October 15, 2009

Validator, need to fill a field if another have custom value

I've made this Validator in order to make the user fill a field if another one have a custom value.
This is based on sfValidatorSchemaCompare.

Create a lib/validator folder and create a new file inside : ValidatorNeedIfField.class.php
Then put this code inside php tags:

 <?php  
   
 /**  
  * ValidatorNeedifField  
  *  
  * @package  symfony  
  * @subpackage validator  
  * @author   João Silva  
  * @version  SVN: $Id: ValidatorNeedIfField.class.php $  
  */  
 class ValidatorNeedIfField extends sfValidatorSchema  
 {  
  const EQUAL       = '==';  
  const NOT_EQUAL     = '!=';  
  const LESS_THAN     = '<';  
  const LESS_THAN_EQUAL  = '<=';  
  const GREATER_THAN    = '>';  
  const GREATER_THAN_EQUAL = '>=';  
   
  /**  
   * Constructor.  
   *  
   * Available options:  
   *  
   * * need_field:     The need field name  
   * * operator:      The comparison operator  
   *             * self::EQUAL  
   *             * self::NOT_EQUAL  
   *             * self::LESS_THAN  
   *             * self::LESS_THAN_EQUAL  
   *             * self::GREATER_THAN  
   *             * self::GREATER_THAN_EQUAL  
   * * right_field:    The right field name  
   * * throw_global_error: Whether to throw a global error (false by default) or an error tied to the need field  
   *  
   * @param string $needField  The need field name  
   * @param string $operator  The operator to apply  
   * @param string $rightField The right field name  
   * @param array $options   An array of options  
   * @param array $messages  An array of error messages  
   *  
   * @see sfValidatorBase  
   */  
  public function __construct($needField, $operator, $rightField, $obj_values = array(), $options = array(), $messages = array())  
  {  
   $this->addOption('need_field', $needField);  
   $this->addOption('operator', $operator);  
   $this->addOption('right_field', $rightField);  
   $this->addOption('obj_values', $obj_values);  
   $this->addOption('throw_global_error', false);  
   
   parent::__construct(null, $options, $messages);  
  }  
   
  /**  
   * @see sfValidatorBase  
   */  
  protected function doClean($values)  
  {  
   if (is_null($values))  
   {  
    $values = array();  
   }  
   
   if (!is_array($values))  
   {  
    throw new InvalidArgumentException('You must pass an array parameter to the clean() method');  
   }  
   
   $needValue = isset($values[$this->getOption('need_field')]) ? $values[$this->getOption('need_field')] : null;  
   $rightValue = isset($values[$this->getOption('right_field')]) ? $values[$this->getOption('right_field')] : null;  
     
   $valid = false;  
     
   foreach($this->getOption('obj_values') as $value){  
    switch ($this->getOption('operator'))  
    {  
     case self::GREATER_THAN:  
      $valid = $value > $rightValue;  
      break;  
     case self::GREATER_THAN_EQUAL:  
      $valid = $value >= $rightValue;  
      break;  
     case self::LESS_THAN:  
      $valid = $value < $rightValue;  
      break;  
     case self::LESS_THAN_EQUAL:  
      $valid = $value <= $rightValue;  
      break;  
     case self::NOT_EQUAL:  
      $valid = $value != $rightValue;  
      break;  
     case self::EQUAL:  
      $valid = $value == $rightValue;  
      break;  
     default:  
      throw new InvalidArgumentException(sprintf('The operator "%s" does not exist.', $this->getOption('operator')));  
    }  
   }  
   
   if ($valid && !trim($needValue) )  
   {  
    $error = new sfValidatorError($this, 'invalid', array(  
     'need_field' => $needValue,  
     'right_field' => $rightValue,  
     'operator'  => $this->getOption('operator'),  
    ));  
    if ($this->getOption('throw_global_error'))  
    {  
     throw $error;  
    }  
   
    throw new sfValidatorErrorSchema($this, array($this->getOption('need_field') => $error));  
   }  
   
   return $values;  
  }  
   
  /**  
   * @see sfValidatorBase  
   */  
  public function asString($indent = 0)  
  {  
   $options = $this->getOptionsWithoutDefaults();  
   $messages = $this->getMessagesWithoutDefaults();  
   unset($options['need_field'], $options['operator'], $options['right_field']);  
   
   $arguments = '';  
   if ($options || $messages)  
   {  
    $arguments = sprintf('(%s%s)',  
     $options ? sfYamlInline::dump($options) : ($messages ? '{}' : ''),  
     $messages ? ', '.sfYamlInline::dump($messages) : ''  
    );  
   }  
   
   return sprintf('%s%s %s%s %s',  
    str_repeat(' ', $indent),  
    $this->getOption('need_field'),  
    $this->getOption('operator'),  
    $arguments,  
    $this->getOption('right_field')  
   );  
  }  
 }  


Now, inside your Form class file you can call it like this inside the function configure():

 $this->validatorSchema->setPostValidator(  
       new ValidatorNeedIfField('need_field', '==', 'right_field', array('value_to_match','with_values'), array(), array('invalid' => 'Error message') ) );  


need_field -> the name of the field that need to be filled
== -> operator to validate
right_field -> the name of the field that have the value to match
value_to_match and with_values -> values that will match the right_field and made the validator test if need_field is filled

No comments:

Post a Comment