Validate_US
[ class tree: Validate_US ] [ index: Validate_US ] [ all elements ]

Source for file US.php

Documentation is available at US.php

  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4: */
  3. /**
  4.  * Specific validation methods for data used in the United States
  5.  *
  6.  * PHP Versions 4 and 5
  7.  *
  8.  * This source file is subject to the New BSD license, That is bundled
  9.  * with this package in the file LICENSE, and is available through
  10.  * the world-wide-web at
  11.  * http://www.opensource.org/licenses/bsd-license.php
  12.  * If you did not receive a copy of the new BSDlicense and are unable
  13.  * to obtain it through the world-wide-web, please send a note to
  14.  * pajoye@php.net so we can mail you a copy immediately.
  15.  *
  16.  * @category  Validate
  17.  * @package   Validate_US
  18.  * @author    Brent Cook <busterbcook@yahoo.com>
  19.  * @author    Tim Gallagher <timg@sunflowerroad.com>
  20.  * @copyright 1997-2005 Brent Cook
  21.  * @license   http://www.opensource.org/licenses/bsd-license.php  new BSD
  22.  * @version   CVS: $Id: US.php,v 1.35 2007/08/07 22:53:48 kguest Exp $
  23.  * @link      http://pear.php.net/package/Validate_US
  24.  */
  25.  
  26. /**
  27.  * Data validation class for the United States
  28.  *
  29.  * This class provides methods to validate:
  30.  *  - Social insurance number (aka SSN)
  31.  *  - Region (state code)
  32.  *  - Postal code
  33.  *  - Telephone number
  34.  *
  35.  * @category  Validate
  36.  * @package   Validate_US
  37.  * @author    Brent Cook <busterbcook@yahoo.com>
  38.  * @author    Tim Gallagher <timg@sunflowerroad.com>
  39.  * @copyright 1997-2005 Brent Cook
  40.  * @license   http://www.opensource.org/licenses/bsd-license.php  new BSD
  41.  * @version   Release: @package_version@
  42.  * @link      http://pear.php.net/package/Validate_US
  43.  */
  44. {
  45.     /**
  46.      * Validates a social security number
  47.      *
  48.      * @param string $ssn         number to validate
  49.      * @param array  $high_groups array of highest issued SSN group numbers
  50.      *
  51.      * @return bool 
  52.      */
  53.     function ssn($ssn$high_groups = null)
  54.     {
  55.         // remove any dashes, spaces, returns, tabs or slashes
  56.         $ssn str_replace(array('-','/',' ',"\t","\n")''$ssn);
  57.  
  58.         // check if this is a 9-digit number
  59.         if (!is_numeric($ssn|| strlen($ssn!= 9{
  60.             return false;
  61.         }
  62.         $area   substr($ssn03);
  63.         $group  intval(substr($ssn32));
  64.         $serial intval(substr($ssn54));
  65.  
  66.         if (!$high_groups{
  67.             $high_groups Validate_US::ssnGetHighGroups();
  68.         }
  69.         return Validate_US::ssnCheck($area$group$serial$high_groups);
  70.     }
  71.  
  72.     /**
  73.     * Returns a range for a supplied group number, which
  74.     * is the middle, two-digit field of a SSN.
  75.     * Group numbers are defined as follows:
  76.     * 1 - Odd numbers, 01 to 09
  77.     * 2 - Even numbers, 10 to 98
  78.     * 3 - Even numbers, 02 to 08
  79.     * 4 - Odd numbers, 11 to 99
  80.     *
  81.     * @param int $groupNumber a group number to check, 00-99
  82.     *
  83.     * @return int 
  84.     */
  85.     function ssnGroupRange($groupNumber)
  86.     {
  87.         if (is_array($groupNumber)) {
  88.             extract($groupNumber);
  89.         }
  90.         if ($groupNumber < 10{
  91.             // is the number odd?
  92.             if ($groupNumber % 2{
  93.                 return 1;
  94.             else {
  95.                 return 3;
  96.             }
  97.         else {
  98.             // is the number odd?
  99.             if ($groupNumber % 2{
  100.                 return 4;
  101.             else {
  102.                 return 2;
  103.             }
  104.         }
  105.     }
  106.  
  107.     /**
  108.      * checks if a Social Security Number is valid
  109.      * needs the first three digits and first two digits and the
  110.      * final four digits as separate integer parameters
  111.      *
  112.      * @param int   $area        3-digit group in a SSN
  113.      * @param int   $group       2-digit group in a SSN
  114.      * @param int   $serial      4-digit group in a SSN
  115.      * @param array $high_groups array of highest issued group numbers
  116.      *                            area number=>group number
  117.      *
  118.      * @return bool true if valid
  119.      */
  120.     function ssnCheck($area$group$serial$high_groups)
  121.     {
  122.         if (is_array($area)) {
  123.             extract($area);
  124.         }
  125.         // perform trivial checks
  126.         // no field should contain all zeros
  127.         if (!($area && $group && $serial)) {
  128.             return false;
  129.         }
  130.  
  131.         // check if this area has been assigned yet
  132.         if (!isset($high_groups[$area])) {
  133.             return false;
  134.         }
  135.  
  136.         $high_group $high_groups[$area];
  137.  
  138.         $high_group_range Validate_US::ssnGroupRange($high_group);
  139.         $group_range      Validate_US::ssnGroupRange($group);
  140.  
  141.         // if the assigned range is higher than this group number, we're OK
  142.         if ($high_group_range $group_range{
  143.             return true;
  144.         elseif ($high_group_range $group_range{
  145.             // if the assigned range is lower than the group number, that's bad
  146.             return false;
  147.         elseif ($high_group >= $group{
  148.             // we must be in the same range, check the actual numbers
  149.             return true;
  150.         }
  151.  
  152.         return false;
  153.     }
  154.  
  155.     /**
  156.      * Gets the most current list the highest SSN group numbers issued
  157.      * from the Social Security Administration website. This info can be
  158.      * cached for performance (and to lessen the load on the SSA website)
  159.      *
  160.      * @param string $uri     Path to the SSA highgroup.txt file
  161.      * @param bool   $is_text Take the $uri param as directly the contents
  162.      *
  163.      * @return array 
  164.      */
  165.     function ssnGetHighGroups($uri 'http://www.ssa.gov/employer/highgroup.txt',
  166.                               $is_text = false)
  167.     {
  168.         /**
  169.          * Stores high groups that have been fetched from any given web page to
  170.          * keep the load down if having to validate more then one ssn in a row
  171.          */
  172.         static $high_groups = array();
  173.         static $lastUri '';
  174.  
  175.         if ($lastUri == $uri && !empty($high_groups)) {
  176.             return $high_groups;
  177.         }
  178.         $lastUri $uri;
  179.  
  180.         if ($is_text{
  181.             $source $uri;
  182.         else {
  183.             if (!$fd @fopen($uri'r')) {
  184.                 $lastUri '';
  185.                 trigger_error('Could not access the SSA High Groups file'
  186.                                E_USER_WARNING);
  187.                 return array();
  188.             }
  189.             $source '';
  190.             while ($data fread($fd2048)) {
  191.                 $source .= $data;
  192.             }
  193.             fclose($fd);
  194.         }
  195.  
  196.         $lines       explode("\n"ereg_replace("[^\n0-9]*"''$source));
  197.         $high_groups = array();
  198.         foreach ($lines as $line{
  199.             $reg '^([0-9]{3})([0-9]{2})([0-9]{3})([0-9]{2})([0-9]{3})'
  200.                  . '([0-9]{2})([0-9]{3})([0-9]{2})([0-9]{3})([0-9]{2})'
  201.                  . '([0-9]{3})([0-9]{2})$';
  202.             if (ereg($reg$line$grouping)) {
  203.                 $high_groups[$grouping[1]]  $grouping[2];
  204.                 $high_groups[$grouping[3]]  $grouping[4];
  205.                 $high_groups[$grouping[5]]  $grouping[6];
  206.                 $high_groups[$grouping[7]]  $grouping[8];
  207.                 $high_groups[$grouping[9]]  $grouping[10];
  208.                 $high_groups[$grouping[11]] $grouping[12];
  209.             }
  210.         }
  211.         return $high_groups;
  212.     }
  213.  
  214.     /**
  215.      * Validates a US Postal Code format (ZIP code)
  216.      *
  217.      * @param string $postalCode the ZIP code to validate
  218.      * @param bool   $strong     optional; strong checks (e.g. against a list
  219.      *                            of postcodes) (not implanted)
  220.      *
  221.      * @return boolean TRUE if code is valid, FALSE otherwise
  222.      * @access public
  223.      * @static
  224.      * @todo Integrate with USPS web API
  225.      */
  226.     function postalCode($postalCode$strong = false)
  227.     {
  228.         return (bool)preg_match('/^[0-9]{5}((-| )[0-9]{4})?$/'$postalCode);
  229.     }
  230.  
  231.     /**
  232.      * Validates a "region" (i.e. state) code
  233.      *
  234.      * @param string $region 2-letter state code
  235.      *
  236.      * @return bool Whether the code is a valid state
  237.      * @static
  238.      */
  239.     function region($region)
  240.     {
  241.         switch (strtoupper($region)) {
  242.         case 'AL':
  243.         case 'AK':
  244.         case 'AZ':
  245.         case 'AR':
  246.         case 'CA':
  247.         case 'CO':
  248.         case 'CT':
  249.         case 'DE':
  250.         case 'DC':
  251.         case 'FL':
  252.         case 'GA':
  253.         case 'HI':
  254.         case 'ID':
  255.         case 'IL':
  256.         case 'IN':
  257.         case 'IA':
  258.         case 'KS':
  259.         case 'KY':
  260.         case 'LA':
  261.         case 'ME':
  262.         case 'MD':
  263.         case 'MA':
  264.         case 'MI':
  265.         case 'MN':
  266.         case 'MS':
  267.         case 'MO':
  268.         case 'MT':
  269.         case 'NE':
  270.         case 'NV':
  271.         case 'NH':
  272.         case 'NJ':
  273.         case 'NM':
  274.         case 'NY':
  275.         case 'NC':
  276.         case 'ND':
  277.         case 'OH':
  278.         case 'OK':
  279.         case 'OR':
  280.         case 'PA':
  281.         case 'RI':
  282.         case 'SC':
  283.         case 'SD':
  284.         case 'TN':
  285.         case 'TX':
  286.         case 'UT':
  287.         case 'VT':
  288.         case 'VA':
  289.         case 'WA':
  290.         case 'WV':
  291.         case 'WI':
  292.         case 'WY':
  293.             return true;
  294.         }
  295.         return false;
  296.     }
  297.  
  298.     /**
  299.      * Validate a US phone number.
  300.      * 
  301.      * Allowed formats
  302.      * <ul>
  303.      *  <li>xxxxxxx <-> 7 digits format</li>
  304.      *  <li>(xxx) xxx-xxxx  <-> area code with brackets around it (or not) +
  305.      *                          phone number with dash or not </li>
  306.      *  <li>xxx xxx-xxxx  <-> area code + number +- dash/space + 4 digits</li>
  307.      *  <li>(1|0) xxx xxx-xxxx  <-> 1 or 0 + area code + 3 digits +- dash/space
  308.      *      + 4 digits</li>
  309.      *  <li>xxxxxxxxxx  <-> 10 digits</li>
  310.      * </ul>
  311.      *
  312.      * or various combination without spaces or dashes.
  313.      * THIS SHOULD EVENTUALLY take a FORMAT in the options, instead
  314.      *
  315.      * @param string $number          phone to validate
  316.      * @param bool   $requireAreaCode require the area code? (default: true)
  317.      *
  318.      * @return bool The valid or invalid phone number
  319.      * @access public
  320.      */
  321.     function phoneNumber($number$requireAreaCode = true)
  322.     {
  323.         if (strlen(trim($number)) <= 6{
  324.             return false;
  325.         }
  326.  
  327.         if (!$requireAreaCode{
  328.             // just seven digits, maybe a space or dash
  329.             if (preg_match('/^[2-9]\d{2}[- ]?\d{4}$/'$number)) {
  330.                 return  true;
  331.             }
  332.         else {
  333.             // ten digits, maybe  spaces and/or dashes and/or parentheses 
  334.             // maybe a 1 or a 0...
  335.             $reg '/^[0-1]?[- ]?(\()?[2-9]\d{2}(?(1)\))[- ]?[2-9]\d{2}[- ]?\d{4}$/';
  336.             if (preg_match($reg,
  337.                            $number)) {
  338.                 return true;
  339.             }
  340.         }
  341.         return false;
  342.     }
  343.  
  344.  
  345.  
  346. }
  347. ?>

Documentation generated on Wed, 12 Dec 2007 15:00:03 -0500 by phpDocumentor 1.4.0. PEAR Logo Copyright © PHP Group 2004.