Location: PHPKode > scripts > Piragibe > piragibe/PGBValidator.php
<?php
/**
 * A validation agent.
 * 
 * This agent is able to perform a comprehensive set of standard basic validations, returning
 * localised messages, should this be the case.
 * @package Piragibe
 * @author Francisco Piragibe
 * @version 1.00
 * @copyright Copyright &copy; 2006, Francisco Piragibe
 * This file is part of The PIRAGIBE Framework.
 *
 * The PIRAGIBE Framework is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * The PIRAGIBE Framework is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with The PIRAGIBE Framework; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */
class PGBValidator {

    /**
     * Extracts the numerical characters (digits, comma, point and the minus sign) from
     * a string.
     * 
     * 123a.5g7 would become 123.57, for instance.
     * @return string the numerical characters in the base string
     * @param string $pBase the base string
     */
    function toDigits( $pBase ) {
    // extrai os digitos de um string qualquer
        $resp = '';
        for( $i=0; $i < strlen($pBase); $i++ ) {
            $c = substr( $pBase, $i, 1 );
            if ( ( $c >= '0' and $c <= '9' ) or ( $c == '-' and $i == 0 ) or ( $c == ',' ) or ( $c == '.' ) ) {
                $resp .= $c;
            }
        }
        return $resp;
    }

    /**
     * Checks if the base string contains only numerical characters.
     * 
     * This is done by comparing the base to the toDigits() version of it.
     * @return boolean true or false, depending on the result
     * @param string $pBase the base string
     */
    function isNumber( $pBase ) {
    // verifica se o string base e puramente numerico
        return ( $this->toDigits($pBase) == $pBase );
    }

    /**
     * Checks to see if the base string is a valid brazilian CPF (taxpayer ID).
     * @return boolean true or false, depending on the result
     * @param string $pBase the base string to verify
     */
    function isCPF( $pBase ) {
    // verifica se o string base e um CPF valido
        $base = sprintf ("%011s",$this->toDigits($pBase));
        if ( $base == '00000000000' ) {
            return false;
        }
        $soma = 0;
        for ($i=0, $p=10; $i<9; $i++, $p--) {
            $soma += (substr($base,$i,1)*$p);
        }
        $dv1 = (($soma*10) % 11) % 10;
        if ( $dv1 != substr($base,9,1) ) {
            return (false);
        }
        $soma = 0;
        for ($i=0, $p=11; $i<10; $i++, $p--) {
            $soma += (substr($base,$i,1)*$p);
        }
        $dv2 = (($soma*10) % 11) % 10;
        if ( $dv2 != substr($base,10,1) ) {
            return (false);
        }
        return (true);
    }

    /**
     * Checks to see if the base string is a valid CNPJ (brazilian company taxpayer ID).
     * @return boolean true or false, depending on the result
     * @param string $pBase the base string to verify
     */
    function isCNPJ( $pBase ) {
    // verifica se o string base e um CNPJ valido
        $base = sprintf ("%014s",$this->toDigits($pBase));
        if ( $base == '00000000000000' ) {
            return false;
        }
        $soma = 0;
        for ($i=0, $p=5; $i<12; $i++, $p--) {
            if ( $p < 2 ) {
                $p = 9;
            }
            $soma += (substr($base,$i,1)*$p);
        }
        $dv1 = (($soma*10) % 11) % 10;
        if ( $dv1 != substr($base,12,1) ) {
            return (false);
        }
        $soma = 0;
        for ($i=0, $p=6; $i<13; $i++, $p--) {
            if ( $p < 2 ) {
                $p = 9;
            }
            $soma += (substr($base,$i,1)*$p);
        }
        $dv2 = (($soma*10) % 11) % 10;
        if ( $dv2 != substr($base,13,1) ) {
            return (false);
        }
        return (true);
    }
    
    /**
     * Breaks a date string into an array having the year, the month and the day as
     * elements.
     * 
     * The resulting array has always three elements: 'Y' => the year, 'M' => the month
     * and 'D' => the day. The format should have marks for the day, month and year positions.
     * DD would mark the day, MM the month and YY or YYYY the year. A format such as
     * 'DD-MM====YYYY' would break a date formatted as 23-02....2006 into an array 
     * correctly.
     * @return array the broken date
     * @param string $pData the date string
     * @param string $pFmt the date format do use when separating date pieces
     */
    function dateToArray( $pData, $pFmt ) {
        $r      = array();
        $wpd    = strpos( $pFmt, 'DD' );
        $wpm    = strpos( $pFmt, 'MM' );
        $wpa    = strpos( $pFmt, 'YY' );
        $wpal   = strpos( $pFmt, 'YYYY' );
        if ( $wpd === false or $wpm === false or $wpa === false ) {
            return $r;
        }
        $wd     = substr( $pData, $wpd, 2 );
        $wm     = substr( $pData, $wpm, 2 );
        $wa     = substr( $pData, $wpa, $wpal ? 4 : 2 );
        $r['Y'] = $wa;
        $r['M'] = $wm;
        $r['D'] = $wd;
        return $r;
    }
    
    /**
     * Compares two date strings, returning their relative position in time.
     * 
     * The dates are supposed to adhere to the user's language default date format.
     * @return integer 1 (date#1 > date#2), 0 (dates are the same) or 2 (date#2 > date#1)
     * @param string $d1 the first date
     * @param string $d2 the second date
     */
    function dateCompare( $d1, $d2 ) {
        $o_nls  = new PGBNlsAgent( 'pt' );
        $w_fmt  = $o_nls->getDateFormat();
        if ( !$this->isDate( $d1, $w_fmt ) or !$this->isDate( $d2, $w_fmt ) ) {
            return NULL;
        }
        $a_d1       = $this->dateToArray( $d1, $w_fmt );
        $a_d2       = $this->dateToArray( $d2, $w_fmt );
        $w_diff     = ( ($a_d1['Y'] * 10000) + ($a_d1['M'] * 100) + $a_d1['D'] ) -
                      ( ($a_d2['Y'] * 10000) + ($a_d2['M'] * 100) + $a_d2['D'] );
        return ( $w_diff>0 ? 1 : ( $w_diff==0 ? 0 : 2 ) );
    }
    
    /**
     * Checks whether the base string is a date valid and complyant to the given format.
     * @return boolean true or false, depending on the result
     * @param string $pBase the base string
     * @param string $pFmt the date format
     */
    function isDate( $pBase, $pFmt ) {
        $a_dt   = $this->dateToArray( $pBase, $pFmt );
        $wd     = $a_dt['D'];
        $wm     = $a_dt['M'];
        $wa     = $a_dt['Y'];
        if ( !$this->isNumber( $wd ) or !$this->isNumber( $wm ) or !$this->isNumber( $wa ) ) {
            return false;
        }
        else {
            //print '<pre>' . checkdate( $wm+0, $wd+0, $wa+0 )?'true':'false' . '</pre>';
            return checkdate( $wm+0, $wd+0, $wa+0 );
        }
    }
    
    /**
    * Validate a PGBField against a PGBValidationDefs
    *
    * @return String error message or NULL, if everything is fine
    * @param mixed $pBase the value to validate
    * @param PGBValidationDefs $pValDef the validation definitions to check against
    */
    function isValid( $pBase, $pValDef ) {
        // our messages
        $ma     = array(
                    'required' => array(
                            'pt' => 'campo obrigatório não preenchido',
                            'en' => 'required field missing'
                            ),
                    'invnum' => array(
                            'pt' => 'número inválido',
                            'en' => 'invalid number'
                            ),
                    'invdate' => array(
                            'pt' => 'data inválida',
                            'en' => 'invalid date'
                            ),
                    'toohigh' => array(
                            'pt' => 'deve ser igual ou inferior a ',
                            'en' => 'this must be less than or equal to '
                            ),
                    'toolow' => array(
                            'pt' => 'deve ser igual ou superior a ',
                            'en' => 'this must be greater than or equal to '
                            ),
                    'cpf' => array(
                            'pt' => 'CPF inválido',
                            'en' => 'invalid CPF number'
                            ),
                    'cnpj' => array(
                            'pt' => 'CNPJ inválido',
                            'en' => 'invalid CNPJ number'
                            ),
                    'notinset' => array(
                            'pt' => 'não está no conjunto de valores possíveis',
                            'en' => 'is not in the set of allowable values'
                            ),
                    'notinquery' => array(
                            'pt' => 'não está na base de dados',
                            'en' => 'is not in the database'
                            )
                    );
        $o_nls  = new PGBNlsAgent( 'pt', $ma );
        // required and missing?
        //print '<pre>' . $pValDef->isRequired()?'true':'false' . '</pre>';
        if ( $pValDef->isRequired() and (is_null( $pBase ) or $pBase == '') ) {
            //print '<pre>req</pre>';
            return $o_nls->getMessage( 'required' );
        }
        if ( is_null( $pBase ) or $pBase == '' ) {
            return NULL;
        }
        // has the correct type?
        $w_typ = $pValDef->getType();
        //print '<pre>' . $w_typ . '</pre>';
        if ( $w_typ == 'number' and !$this->isNumber( $pBase ) ) {
            return $o_nls->getMessage( 'invnum' );
        }
        elseif ( $w_typ == 'date' and !$this->isDate( $pBase, $o_nls->getDateFormat() ) ) {
            return $o_nls->getMessage( 'invdate' );
        }
        elseif ( $w_typ == 'cpf' and !$this->isCPF( $pBase ) ) {
            return $o_nls->getMessage( 'cpf' );
        }
        elseif ( $w_typ == 'cnpj' and !$this->isCPF( $pBase ) ) {
            return $o_nls->getMessage( 'cnpj' );
        }
        // is between given boundaries?
        $wlb = $pValDef->getLowerBound();
        $wub = $pValDef->getUpperBound();
        if ( !is_null($wlb) ) {
            if ( $pBase < $wlb ) {
                return $o_nls->getMessage( 'toolow' ) . $wlb;
            }
        }
        if ( !is_null($wub) ) {
            if ( $pBase > $wub ) {
                return $o_nls->getMessage( 'toohigh' ) . $wub;
            }
        }
        // is in the given discrete set?
        $w_set = $pValDef->getBaseSet();
        if ( $w_set ) {
            if ( !isset( $w_set[ $pBase ] ) ) {
                return $o_nls->getMessage( 'notinset' );
            }
        }
        // is in the given SQL query?
        $w_bq = $pValDef->getBaseQuery();
        if ( is_array( $w_bq ) ) {
            $w_sql = $w_bq[ 'sql' ];
            $o_con = $w_bq[ 'conn' ];
            // substitui ? pelo valor do campo corrente
            $w_sqlr= str_replace( '?', $pBase, $w_sql );
            $o_rs  = $o_con->query( $w_sqlr );
            //print $w_sqlr . ' - ' . $o_rs->rowCount() . "\n";
            if ( $o_rs->rowCount() == 0 ) {
                return $o_nls->getMessage( 'notinquery' );
            }
        }
        // return OK
        return NULL;
    }

}
?>
Return current item: Piragibe