Source for file Validator.php

Documentation is available at Validator.php

  1. <?php
  2. /*
  3.  *  $Id: Validator.php 2193 2007-08-10 06:01:54Z nicobn $
  4.  *
  5.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  6.  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  7.  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  8.  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  9.  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  10.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  11.  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  12.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  13.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  14.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  15.  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  16.  *
  17.  * This software consists of voluntary contributions made by many individuals
  18.  * and is licensed under the LGPL. For more information, see
  19.  * <http://www.phpdoctrine.com>.
  20.  */
  21. /**
  22.  * Doctrine_Validator
  23.  * Doctrine_Validator performs validations in record properties
  24.  *
  25.  * @package     Doctrine
  26.  * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
  27.  * @category    Object Relational Mapping
  28.  * @link        www.phpdoctrine.com
  29.  * @since       1.0
  30.  * @version     $Revision: 2193 $
  31.  * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
  32.  */
  33. {
  34.     /**
  35.      * @var array $validators           an array of validator objects
  36.      */
  37.     private static $validators  array();
  38.     /**
  39.      * returns a validator object
  40.      *
  41.      * @param string $name 
  42.      * @return Doctrine_Validator_Interface 
  43.      */
  44.     public static function getValidator($name)
  45.     {
  46.         if isset(self::$validators[$name])) {
  47.             $class 'Doctrine_Validator_' ucwords(strtolower($name));
  48.             if (class_exists($class)) {
  49.                 self::$validators[$namenew $class;
  50.             else {
  51.                 throw new Doctrine_Exception("Validator named '$namenot available.");
  52.             }
  53.  
  54.         }
  55.         return self::$validators[$name];
  56.     }
  57.     /**
  58.      * validates a given record and saves possible errors
  59.      * in Doctrine_Validator::$stack
  60.      *
  61.      * @param Doctrine_Record $record 
  62.      * @return void 
  63.      */
  64.     public function validateRecord(Doctrine_Record $record)
  65.     {
  66.         $columns   $record->getTable()->getColumns();
  67.         $component $record->getTable()->getComponentName();
  68.  
  69.         $errorStack $record->getErrorStack();
  70.  
  71.         // if record is transient all fields will be validated
  72.         // if record is persistent only the modified fields will be validated
  73.         $data ($record->exists()) $record->getModified($record->getData();
  74.  
  75.         $err      array();
  76.         foreach ($data as $key => $value{
  77.             if ($value === self::$_null{
  78.                 $value null;
  79.             elseif ($value instanceof Doctrine_Record{
  80.                 $value $value->getIncremented();
  81.             }
  82.  
  83.             $column $columns[$key];
  84.  
  85.             if ($column['type'== 'enum'{
  86.                 $value $record->getTable()->enumIndex($key$value);
  87.  
  88.                 if ($value === false{
  89.                     $errorStack->add($key'enum');
  90.                     continue;
  91.                 }
  92.             }
  93.  
  94.             if ($record->getTable()->getAttribute(Doctrine::ATTR_AUTO_LENGTH_VLD)) {
  95.                 if (!$this->validateLength($column$key$value)) {
  96.                     $errorStack->add($key'length');
  97.  
  98.                     continue;
  99.                 }
  100.             }
  101.  
  102.             foreach ($column as $name => $args{
  103.                 if (empty($name)
  104.                     || $name == 'primary'
  105.                     || $name == 'protected'
  106.                     || $name == 'autoincrement'
  107.                     || $name == 'default'
  108.                     || $name == 'values'
  109.                     || $name == 'sequence'
  110.                     || $name == 'zerofill'{
  111.                     continue;
  112.                 }
  113.  
  114.                 if (strtolower($name=== 'notnull' && isset($column['autoincrement'])) {
  115.                     continue;
  116.                 }
  117.  
  118.                 if (strtolower($name== 'length'{
  119.                     if (!$record->getTable()->getAttribute(Doctrine::ATTR_AUTO_LENGTH_VLD)) {
  120.                         if (!$this->validateLength($column$key$value)) {
  121.                             $errorStack->add($key'length');
  122.                         }
  123.                     }
  124.                     continue;
  125.                 }
  126.  
  127.                 if (strtolower($name== 'type'{
  128.                     if (!$record->getTable()->getAttribute(Doctrine::ATTR_AUTO_TYPE_VLD)) {
  129.                         if self::isValidType($value$column['type'])) {
  130.                             $errorStack->add($key'type');
  131.                         }
  132.                     }
  133.                     continue;
  134.                 }
  135.  
  136.                 $validator self::getValidator($name);
  137.                 if $validator->validate($record$key$value$args)) {
  138.                     $errorStack->add($key$name);
  139.  
  140.                     //$err[$key] = 'not valid';
  141.  
  142.                     // errors found quit validation looping for this column
  143.                     //break;
  144.                 }
  145.             }
  146.  
  147.             if ($record->getTable()->getAttribute(Doctrine::ATTR_AUTO_TYPE_VLD)) {
  148.                 if self::isValidType($value$column['type'])) {
  149.                     $errorStack->add($key'type');
  150.                     continue;
  151.                 }
  152.             }
  153.         }
  154.     }
  155.     /**
  156.      * Validates the length of a field.
  157.      */
  158.     private function validateLength($column$key$value)
  159.     {
  160.         if ($column['type'== 'timestamp' || $column['type'== 'integer'{
  161.             return true;
  162.         elseif ($column['type'== 'array' || $column['type'== 'object'{
  163.             $length strlen(serialize($value));
  164.         else {
  165.             $length strlen($value);
  166.         }
  167.  
  168.         if ($length $column['length']{
  169.             return false;
  170.         }
  171.         return true;
  172.     }
  173.     /**
  174.      * whether or not this validator has errors
  175.      *
  176.      * @return boolean 
  177.      */
  178.     public function hasErrors()
  179.     {
  180.         return (count($this->stack0);
  181.     }
  182.     /**
  183.      * converts a doctrine type to native php type
  184.      *
  185.      * @param $doctrineType 
  186.      * @return string 
  187.      */
  188.     public static function phpType($doctrineType)
  189.     {
  190.         switch ($doctrineType{
  191.             case 'enum':
  192.                 return 'integer';
  193.             case 'blob':
  194.             case 'clob':
  195.             case 'mbstring':
  196.             case 'timestamp':
  197.             case 'date':
  198.             case 'gzip':
  199.                 return 'string';
  200.                 break;
  201.             default:
  202.                 return $doctrineType;
  203.         }
  204.     }
  205.     /**
  206.      * returns whether or not the given variable is
  207.      * valid type
  208.      *
  209.      * @param mixed $var 
  210.      * @param string $type 
  211.      * @return boolean 
  212.      */
  213.     public static function isValidType($var$type)
  214.     {
  215.         if ($type == 'boolean'{
  216.             return true;
  217.         }
  218.  
  219.         $looseType self::gettype($var);
  220.         $type      self::phpType($type);
  221.  
  222.         switch ($looseType{
  223.             case 'float':
  224.             case 'double':
  225.             case 'integer':
  226.                 if ($type == 'string' || $type == 'float'{
  227.                     return true;
  228.                 }
  229.             case 'string':
  230.             case 'array':
  231.             case 'object':
  232.                 return ($type === $looseType);
  233.                 break;
  234.             case 'NULL':
  235.                 return true;
  236.                 break;
  237.         };
  238.     }
  239.     /**
  240.      * returns the type of loosely typed variable
  241.      *
  242.      * @param mixed $var 
  243.      * @return string 
  244.      */
  245.     public static function gettype($var)
  246.     {
  247.         $type gettype($var);
  248.         switch ($type{
  249.             case 'string':
  250.                 if (preg_match("/^[0-9]+$/",$var)) {
  251.                     return 'integer';
  252.                 elseif (is_numeric($var)) {
  253.                     return 'float';
  254.                 else {
  255.                     return $type;
  256.                 }
  257.                 break;
  258.             default:
  259.                 return $type;
  260.         };
  261.     }
  262. }