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

Source for file Validate.php

Documentation is available at Validate.php

  1. <?php
  2. /**
  3.  * PEAR_Validate
  4.  *
  5.  * PHP versions 4 and 5
  6.  *
  7.  * @category   pear
  8.  * @package    PEAR
  9.  * @author     Greg Beaver <cellog@php.net>
  10.  * @copyright  1997-2009 The Authors
  11.  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
  12.  * @version    CVS: $Id: Validate.php 313023 2011-07-06 19:17:11Z dufuz $
  13.  * @link       http://pear.php.net/package/PEAR
  14.  * @since      File available since Release 1.4.0a1
  15.  */
  16. /**#@+
  17.  * Constants for install stage
  18.  */
  19. define('PEAR_VALIDATE_INSTALLING'1);
  20. define('PEAR_VALIDATE_UNINSTALLING'2)// this is not bit-mapped like the others
  21. define('PEAR_VALIDATE_NORMAL'3);
  22. define('PEAR_VALIDATE_DOWNLOADING'4)// this is not bit-mapped like the others
  23. define('PEAR_VALIDATE_PACKAGING'7);
  24. /**#@-*/
  25. require_once 'PEAR/Common.php';
  26. require_once 'PEAR/Validator/PECL.php';
  27.  
  28. /**
  29.  * Validation class for package.xml - channel-level advanced validation
  30.  * @category   pear
  31.  * @package    PEAR
  32.  * @author     Greg Beaver <cellog@php.net>
  33.  * @copyright  1997-2009 The Authors
  34.  * @license    http://opensource.org/licenses/bsd-license.php New BSD License
  35.  * @version    Release: 1.9.4
  36.  * @link       http://pear.php.net/package/PEAR
  37.  * @since      Class available since Release 1.4.0a1
  38.  */
  39. {
  40.     var $packageregex = _PEAR_COMMON_PACKAGE_NAME_PREG;
  41.     /**
  42.      * @var PEAR_PackageFile_v1|PEAR_PackageFile_v2
  43.      */
  44.     var $_packagexml;
  45.     /**
  46.      * @var int one of the PEAR_VALIDATE_* constants
  47.      */
  48.     var $_state = PEAR_VALIDATE_NORMAL;
  49.     /**
  50.      * Format: ('error' => array('field' => name, 'reason' => reason), 'warning' => same)
  51.      * @var array 
  52.      * @access private
  53.      */
  54.     var $_failures = array('error' => array()'warning' => array());
  55.  
  56.     /**
  57.      * Override this method to handle validation of normal package names
  58.      * @param string 
  59.      * @return bool 
  60.      * @access protected
  61.      */
  62.     function _validPackageName($name)
  63.     {
  64.         return (bool) preg_match('/^' $this->packageregex . '\\z/'$name);
  65.     }
  66.  
  67.     /**
  68.      * @param string package name to validate
  69.      * @param string name of channel-specific validation package
  70.      * @final
  71.      */
  72.     function validPackageName($name$validatepackagename = false)
  73.     {
  74.         if ($validatepackagename{
  75.             if (strtolower($name== strtolower($validatepackagename)) {
  76.                 return (bool) preg_match('/^[a-zA-Z0-9_]+(?:\.[a-zA-Z0-9_]+)*\\z/'$name);
  77.             }
  78.         }
  79.         return $this->_validPackageName($name);
  80.     }
  81.  
  82.     /**
  83.      * This validates a bundle name, and bundle names must conform
  84.      * to the PEAR naming convention, so the method is final and static.
  85.      * @param string 
  86.      * @final
  87.      * @static
  88.      */
  89.     function validGroupName($name)
  90.     {
  91.         return (bool) preg_match('/^' _PEAR_COMMON_PACKAGE_NAME_PREG . '\\z/'$name);
  92.     }
  93.  
  94.     /**
  95.      * Determine whether $state represents a valid stability level
  96.      * @param string 
  97.      * @return bool 
  98.      * @static
  99.      * @final
  100.      */
  101.     function validState($state)
  102.     {
  103.         return in_array($statearray('snapshot''devel''alpha''beta''stable'));
  104.     }
  105.  
  106.     /**
  107.      * Get a list of valid stability levels
  108.      * @return array 
  109.      * @static
  110.      * @final
  111.      */
  112.     function getValidStates()
  113.     {
  114.         return array('snapshot''devel''alpha''beta''stable');
  115.     }
  116.  
  117.     /**
  118.      * Determine whether a version is a properly formatted version number that can be used
  119.      * by version_compare
  120.      * @param string 
  121.      * @return bool 
  122.      * @static
  123.      * @final
  124.      */
  125.     function validVersion($ver)
  126.     {
  127.         return (bool) preg_match(PEAR_COMMON_PACKAGE_VERSION_PREG$ver);
  128.     }
  129.  
  130.     /**
  131.      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
  132.      */
  133.     function setPackageFile(&$pf)
  134.     {
  135.         $this->_packagexml &$pf;
  136.     }
  137.  
  138.     /**
  139.      * @access private
  140.      */
  141.     function _addFailure($field$reason)
  142.     {
  143.         $this->_failures['errors'][= array('field' => $field'reason' => $reason);
  144.     }
  145.  
  146.     /**
  147.      * @access private
  148.      */
  149.     function _addWarning($field$reason)
  150.     {
  151.         $this->_failures['warnings'][= array('field' => $field'reason' => $reason);
  152.     }
  153.  
  154.     function getFailures()
  155.     {
  156.         $failures $this->_failures;
  157.         $this->_failures = array('warnings' => array()'errors' => array());
  158.         return $failures;
  159.     }
  160.  
  161.     /**
  162.      * @param int one of the PEAR_VALIDATE_* constants
  163.      */
  164.     function validate($state = null)
  165.     {
  166.         if (!isset($this->_packagexml)) {
  167.             return false;
  168.         }
  169.         if ($state !== null{
  170.             $this->_state $state;
  171.         }
  172.         $this->_failures = array('warnings' => array()'errors' => array());
  173.         $this->validatePackageName();
  174.         $this->validateVersion();
  175.         $this->validateMaintainers();
  176.         $this->validateDate();
  177.         $this->validateSummary();
  178.         $this->validateDescription();
  179.         $this->validateLicense();
  180.         $this->validateNotes();
  181.         if ($this->_packagexml->getPackagexmlVersion(== '1.0'{
  182.             $this->validateState();
  183.             $this->validateFilelist();
  184.         elseif ($this->_packagexml->getPackagexmlVersion(== '2.0' ||
  185.                   $this->_packagexml->getPackagexmlVersion(== '2.1'{
  186.             $this->validateTime();
  187.             $this->validateStability();
  188.             $this->validateDeps();
  189.             $this->validateMainFilelist();
  190.             $this->validateReleaseFilelist();
  191.             //$this->validateGlobalTasks();
  192.             $this->validateChangelog();
  193.         }
  194.         return !((bool) count($this->_failures['errors']));
  195.     }
  196.  
  197.     /**
  198.      * @access protected
  199.      */
  200.     function validatePackageName()
  201.     {
  202.         if ($this->_state == PEAR_VALIDATE_PACKAGING ||
  203.               $this->_state == PEAR_VALIDATE_NORMAL{
  204.             if (($this->_packagexml->getPackagexmlVersion(== '2.0' ||
  205.                  $this->_packagexml->getPackagexmlVersion(== '2.1'&&
  206.                   $this->_packagexml->getExtends()) {
  207.                 $version $this->_packagexml->getVersion('';
  208.                 $name $this->_packagexml->getPackage();
  209.                 $test array_shift($a explode('.'$version));
  210.                 if ($test == '0'{
  211.                     return true;
  212.                 }
  213.                 $vlen strlen($test);
  214.                 $majver substr($namestrlen($name$vlen);
  215.                 while ($majver && !is_numeric($majver{0})) {
  216.                     $majver substr($majver1);
  217.                 }
  218.                 if ($majver != $test{
  219.                     $this->_addWarning('package'"package $name extends package " .
  220.                         $this->_packagexml->getExtends(' and so the name should ' .
  221.                         'have a postfix equal to the major version like "' .
  222.                         $this->_packagexml->getExtends($test '"');
  223.                     return true;
  224.                 elseif (substr($name0strlen($name$vlen!=
  225.                             $this->_packagexml->getExtends()) {
  226.                     $this->_addWarning('package'"package $name extends package " .
  227.                         $this->_packagexml->getExtends(' and so the name must ' .
  228.                         'be an extension like "' $this->_packagexml->getExtends(.
  229.                         $test '"');
  230.                     return true;
  231.                 }
  232.             }
  233.         }
  234.         if (!$this->validPackageName($this->_packagexml->getPackage())) {
  235.             $this->_addFailure('name''package name "' .
  236.                 $this->_packagexml->getPackage('" is invalid');
  237.             return false;
  238.         }
  239.     }
  240.  
  241.     /**
  242.      * @access protected
  243.      */
  244.     function validateVersion()
  245.     {
  246.         if ($this->_state != PEAR_VALIDATE_PACKAGING{
  247.             if (!$this->validVersion($this->_packagexml->getVersion())) {
  248.                 $this->_addFailure('version',
  249.                     'Invalid version number "' $this->_packagexml->getVersion('"');
  250.             }
  251.             return false;
  252.         }
  253.         $version $this->_packagexml->getVersion();
  254.         $versioncomponents explode('.'$version);
  255.         if (count($versioncomponents!= 3{
  256.             $this->_addWarning('version',
  257.                 'A version number should have 3 decimals (x.y.z)');
  258.             return true;
  259.         }
  260.         $name $this->_packagexml->getPackage();
  261.         // version must be based upon state
  262.         switch ($this->_packagexml->getState()) {
  263.             case 'snapshot' :
  264.                 return true;
  265.             case 'devel' :
  266.                 if ($versioncomponents[0'a' == '0a'{
  267.                     return true;
  268.                 }
  269.                 if ($versioncomponents[0== 0{
  270.                     $versioncomponents[0'0';
  271.                     $this->_addWarning('version',
  272.                         'version "' $version '" should be "' .
  273.                         implode('.' ,$versioncomponents'"');
  274.                 else {
  275.                     $this->_addWarning('version',
  276.                         'packages with devel stability must be < version 1.0.0');
  277.                 }
  278.                 return true;
  279.             break;
  280.             case 'alpha' :
  281.             case 'beta' :
  282.                 // check for a package that extends a package,
  283.                 // like Foo and Foo2
  284.                 if ($this->_state == PEAR_VALIDATE_PACKAGING{
  285.                     if (substr($versioncomponents[2]12== 'rc'{
  286.                         $this->_addFailure('version''Release Candidate versions ' .
  287.                             'must have capital RC, not lower-case rc');
  288.                         return false;
  289.                     }
  290.                 }
  291.                 if (!$this->_packagexml->getExtends()) {
  292.                     if ($versioncomponents[0== '1'{
  293.                         if ($versioncomponents[2]{0== '0'{
  294.                             if ($versioncomponents[2== '0'{
  295.                                 // version 1.*.0000
  296.                                 $this->_addWarning('version',
  297.                                     'version 1.' $versioncomponents[1.
  298.                                         '.0 probably should not be alpha or beta');
  299.                                 return true;
  300.                             elseif (strlen($versioncomponents[2]> 1{
  301.                                 // version 1.*.0RC1 or 1.*.0beta24 etc.
  302.                                 return true;
  303.                             else {
  304.                                 // version 1.*.0
  305.                                 $this->_addWarning('version',
  306.                                     'version 1.' $versioncomponents[1.
  307.                                         '.0 probably should not be alpha or beta');
  308.                                 return true;
  309.                             }
  310.                         else {
  311.                             $this->_addWarning('version',
  312.                                 'bugfix versions (1.3.x where x > 0) probably should ' .
  313.                                 'not be alpha or beta');
  314.                             return true;
  315.                         }
  316.                     elseif ($versioncomponents[0!= '0'{
  317.                         $this->_addWarning('version',
  318.                             'major versions greater than 1 are not allowed for packages ' .
  319.                             'without an <extends> tag or an identical postfix (foo2 v2.0.0)');
  320.                         return true;
  321.                     }
  322.                     if ($versioncomponents[0'a' == '0a'{
  323.                         return true;
  324.                     }
  325.                     if ($versioncomponents[0== 0{
  326.                         $versioncomponents[0'0';
  327.                         $this->_addWarning('version',
  328.                             'version "' $version '" should be "' .
  329.                             implode('.' ,$versioncomponents'"');
  330.                     }
  331.                 else {
  332.                     $vlen strlen($versioncomponents[0'');
  333.                     $majver substr($namestrlen($name$vlen);
  334.                     while ($majver && !is_numeric($majver{0})) {
  335.                         $majver substr($majver1);
  336.                     }
  337.                     if (($versioncomponents[0!= 0&& $majver != $versioncomponents[0]{
  338.                         $this->_addWarning('version''first version number "' .
  339.                             $versioncomponents[0'" must match the postfix of ' .
  340.                             'package name "' $name '" (' .
  341.                             $majver ')');
  342.                         return true;
  343.                     }
  344.                     if ($versioncomponents[0== $majver{
  345.                         if ($versioncomponents[2]{0== '0'{
  346.                             if ($versioncomponents[2== '0'{
  347.                                 // version 2.*.0000
  348.                                 $this->_addWarning('version',
  349.                                     "version $majver." . $versioncomponents[1.
  350.                                         '.0 probably should not be alpha or beta');
  351.                                 return false;
  352.                             elseif (strlen($versioncomponents[2]> 1{
  353.                                 // version 2.*.0RC1 or 2.*.0beta24 etc.
  354.                                 return true;
  355.                             else {
  356.                                 // version 2.*.0
  357.                                 $this->_addWarning('version',
  358.                                     "version $majver." . $versioncomponents[1.
  359.                                         '.0 cannot be alpha or beta');
  360.                                 return true;
  361.                             }
  362.                         else {
  363.                             $this->_addWarning('version',
  364.                                 "bugfix versions ($majver.x.y where y > 0) should " .
  365.                                 'not be alpha or beta');
  366.                             return true;
  367.                         }
  368.                     elseif ($versioncomponents[0!= '0'{
  369.                         $this->_addWarning('version',
  370.                             "only versions 0.x.y and $majver.x.y are allowed for alpha/beta releases");
  371.                         return true;
  372.                     }
  373.                     if ($versioncomponents[0'a' == '0a'{
  374.                         return true;
  375.                     }
  376.                     if ($versioncomponents[0== 0{
  377.                         $versioncomponents[0'0';
  378.                         $this->_addWarning('version',
  379.                             'version "' $version '" should be "' .
  380.                             implode('.' ,$versioncomponents'"');
  381.                     }
  382.                 }
  383.                 return true;
  384.             break;
  385.             case 'stable' :
  386.                 if ($versioncomponents[0== '0'{
  387.                     $this->_addWarning('version''versions less than 1.0.0 cannot ' .
  388.                     'be stable');
  389.                     return true;
  390.                 }
  391.                 if (!is_numeric($versioncomponents[2])) {
  392.                     if (preg_match('/\d+(rc|a|alpha|b|beta)\d*/i',
  393.                           $versioncomponents[2])) {
  394.                         $this->_addWarning('version''version "' $version '" or any ' .
  395.                             'RC/beta/alpha version cannot be stable');
  396.                         return true;
  397.                     }
  398.                 }
  399.                 // check for a package that extends a package,
  400.                 // like Foo and Foo2
  401.                 if ($this->_packagexml->getExtends()) {
  402.                     $vlen strlen($versioncomponents[0'');
  403.                     $majver substr($namestrlen($name$vlen);
  404.                     while ($majver && !is_numeric($majver{0})) {
  405.                         $majver substr($majver1);
  406.                     }
  407.                     if (($versioncomponents[0!= 0&& $majver != $versioncomponents[0]{
  408.                         $this->_addWarning('version''first version number "' .
  409.                             $versioncomponents[0'" must match the postfix of ' .
  410.                             'package name "' $name '" (' .
  411.                             $majver ')');
  412.                         return true;
  413.                     }
  414.                 elseif ($versioncomponents[0> 1{
  415.                     $this->_addWarning('version''major version x in x.y.z may not be greater than ' .
  416.                         '1 for any package that does not have an <extends> tag');
  417.                 }
  418.                 return true;
  419.             break;
  420.             default :
  421.                 return false;
  422.             break;
  423.         }
  424.     }
  425.  
  426.     /**
  427.      * @access protected
  428.      */
  429.     function validateMaintainers()
  430.     {
  431.         // maintainers can only be truly validated server-side for most channels
  432.         // but allow this customization for those who wish it
  433.         return true;
  434.     }
  435.  
  436.     /**
  437.      * @access protected
  438.      */
  439.     function validateDate()
  440.     {
  441.         if ($this->_state == PEAR_VALIDATE_NORMAL ||
  442.               $this->_state == PEAR_VALIDATE_PACKAGING{
  443.  
  444.             if (!preg_match('/(\d\d\d\d)\-(\d\d)\-(\d\d)/',
  445.                   $this->_packagexml->getDate()$res||
  446.                   count($res< 4
  447.                   || !checkdate($res[2]$res[3]$res[1])
  448.                 {
  449.                 $this->_addFailure('date''invalid release date "' .
  450.                     $this->_packagexml->getDate('"');
  451.                 return false;
  452.             }
  453.  
  454.             if ($this->_state == PEAR_VALIDATE_PACKAGING &&
  455.                   $this->_packagexml->getDate(!= date('Y-m-d')) {
  456.                 $this->_addWarning('date''Release Date "' .
  457.                     $this->_packagexml->getDate('" is not today');
  458.             }
  459.         }
  460.         return true;
  461.     }
  462.  
  463.     /**
  464.      * @access protected
  465.      */
  466.     function validateTime()
  467.     {
  468.         if (!$this->_packagexml->getTime()) {
  469.             // default of no time value set
  470.             return true;
  471.         }
  472.  
  473.         // packager automatically sets time, so only validate if pear validate is called
  474.         if ($this->_state PEAR_VALIDATE_NORMAL{
  475.             if (!preg_match('/\d\d:\d\d:\d\d/',
  476.                   $this->_packagexml->getTime())) {
  477.                 $this->_addFailure('time''invalid release time "' .
  478.                     $this->_packagexml->getTime('"');
  479.                 return false;
  480.             }
  481.  
  482.             $result preg_match('|\d{2}\:\d{2}\:\d{2}|'$this->_packagexml->getTime()$matches);
  483.             if ($result === false || empty($matches)) {
  484.                 $this->_addFailure('time''invalid release time "' .
  485.                     $this->_packagexml->getTime('"');
  486.                 return false;
  487.             }
  488.         }
  489.  
  490.         return true;
  491.     }
  492.  
  493.     /**
  494.      * @access protected
  495.      */
  496.     function validateState()
  497.     {
  498.         // this is the closest to "final" php4 can get
  499.         if (!PEAR_Validate::validState($this->_packagexml->getState())) {
  500.             if (strtolower($this->_packagexml->getState(== 'rc')) {
  501.                 $this->_addFailure('state''RC is not a state, it is a version ' .
  502.                     'postfix, use ' $this->_packagexml->getVersion('RC1, state beta');
  503.             }
  504.             $this->_addFailure('state''invalid release state "' .
  505.                 $this->_packagexml->getState('", must be one of: ' .
  506.                 implode(', 'PEAR_Validate::getValidStates()));
  507.             return false;
  508.         }
  509.         return true;
  510.     }
  511.  
  512.     /**
  513.      * @access protected
  514.      */
  515.     function validateStability()
  516.     {
  517.         $ret = true;
  518.         $packagestability $this->_packagexml->getState();
  519.         $apistability $this->_packagexml->getState('api');
  520.         if (!PEAR_Validate::validState($packagestability)) {
  521.             $this->_addFailure('state''invalid release stability "' .
  522.                 $this->_packagexml->getState('", must be one of: ' .
  523.                 implode(', 'PEAR_Validate::getValidStates()));
  524.             $ret = false;
  525.         }
  526.         $apistates PEAR_Validate::getValidStates();
  527.         array_shift($apistates)// snapshot is not allowed
  528.         if (!in_array($apistability$apistates)) {
  529.             $this->_addFailure('state''invalid API stability "' .
  530.                 $this->_packagexml->getState('api''", must be one of: ' .
  531.                 implode(', '$apistates));
  532.             $ret = false;
  533.         }
  534.         return $ret;
  535.     }
  536.  
  537.     /**
  538.      * @access protected
  539.      */
  540.     function validateSummary()
  541.     {
  542.         return true;
  543.     }
  544.  
  545.     /**
  546.      * @access protected
  547.      */
  548.     function validateDescription()
  549.     {
  550.         return true;
  551.     }
  552.  
  553.     /**
  554.      * @access protected
  555.      */
  556.     function validateLicense()
  557.     {
  558.         return true;
  559.     }
  560.  
  561.     /**
  562.      * @access protected
  563.      */
  564.     function validateNotes()
  565.     {
  566.         return true;
  567.     }
  568.  
  569.     /**
  570.      * for package.xml 2.0 only - channels can't use package.xml 1.0
  571.      * @access protected
  572.      */
  573.     function validateDependencies()
  574.     {
  575.         return true;
  576.     }
  577.  
  578.     /**
  579.      * for package.xml 1.0 only
  580.      * @access private
  581.      */
  582.     function _validateFilelist()
  583.     {
  584.         return true; // placeholder for now
  585.     }
  586.  
  587.     /**
  588.      * for package.xml 2.0 only
  589.      * @access protected
  590.      */
  591.     function validateMainFilelist()
  592.     {
  593.         return true; // placeholder for now
  594.     }
  595.  
  596.     /**
  597.      * for package.xml 2.0 only
  598.      * @access protected
  599.      */
  600.     function validateReleaseFilelist()
  601.     {
  602.         return true; // placeholder for now
  603.     }
  604.  
  605.     /**
  606.      * @access protected
  607.      */
  608.     function validateChangelog()
  609.     {
  610.         return true;
  611.     }
  612.  
  613.     /**
  614.      * @access protected
  615.      */
  616.     function validateFilelist()
  617.     {
  618.         return true;
  619.     }
  620.  
  621.     /**
  622.      * @access protected
  623.      */
  624.     function validateDeps()
  625.     {
  626.         return true;
  627.     }
  628. }

Documentation generated on Wed, 06 Jul 2011 23:31:39 +0000 by phpDocumentor 1.4.3. PEAR Logo Copyright © PHP Group 2004.