home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2008 February / PCWFEB08.iso / Software / Resources / Developers / XAMPP 1.5.4 / Windows installer / xampp-win32-1.5.4-installer.exe / xampp / php / pear / PHP / CompatInfo.php < prev   
Encoding:
PHP Script  |  2005-12-02  |  18.9 KB  |  490 lines

  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4: */
  3. // +----------------------------------------------------------------------+
  4. // | PHP version 4                                                        |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 1997-2004 The PHP Group                                |
  7. // +----------------------------------------------------------------------+
  8. // | This source file is subject to version 3.0 of the PHP license,       |
  9. // | that is bundled with this package in the file LICENSE, and is        |
  10. // | available through the world-wide-web at the following url:           |
  11. // | http://www.php.net/license/3_0.txt.                                  |
  12. // | If you did not receive a copy of the PHP license and are unable to   |
  13. // | obtain it through the world-wide-web, please send a note to          |
  14. // | license@php.net so we can mail you a copy immediately.               |
  15. // +----------------------------------------------------------------------+
  16. // | Authors: Davey Shafik <davey@php.net>                                |
  17. // +----------------------------------------------------------------------+
  18. //
  19. // $Id: CompatInfo.php,v 1.15 2005/03/06 00:38:01 davey Exp $
  20.  
  21. /**
  22.  * Check Compatibility of chunk of PHP code
  23.  * @package PHP_CompatInfo
  24.  * @category PHP
  25.  */
  26.  
  27. /**
  28.  * An array of function init versions and extension
  29.  */
  30. require_once 'PHP/data/func_array.php';
  31.  
  32. /**
  33.  * An array of constants and their init versions
  34.  */
  35. require_once 'PHP/data/const_array.php';
  36.  
  37. /**
  38.  * Check Compatibility of chunk of PHP code
  39.  *
  40.  * @package PHP_CompatInfo
  41.  * @author Davey Shafik <davey@php.net>
  42.  * @copyright Copyright 2003 Davey Shafik and Synaptic Media. All Rights Reserved.
  43.  * @example docs/examples/checkConstants.php Example that shows minimum version with Constants
  44.  * @example docs/examples/parseFile.php Example on how to parse a file
  45.  * @example docs/examples/parseDir.php Example on how to parse a directory
  46.  * @example docs/examples/parseArray.php Example on using using parseArray() to parse a script
  47.  * @example docs/examples/parseString.php Example on how to parse a string
  48.  * @example docs/examples/Cli.php Example of using PHP_CompatInfo_Cli
  49.  */
  50.  
  51. class PHP_CompatInfo {
  52.  
  53.     /**
  54.      * @var string Earliest version of PHP to use
  55.      */
  56.  
  57.     var $latest_version = '4.0.0';
  58.  
  59.     /**
  60.      * @var boolean Toggle parseDir recursion
  61.      */
  62.  
  63.     var $recurse_dir = true;
  64.  
  65.     /**
  66.      * Parse a file for its Compatibility info
  67.      *
  68.      * @param string $file Path of File to parse
  69.      * @param array $options An array of options where:
  70.      *                          'debug' contains a boolean
  71.      *                              to control whether extra
  72.      *                              ouput is shown.
  73.      *                          'ignore_functions' contains an array
  74.      *                              of functions to ignore when
  75.      *                              calculating the version needed.
  76.      * @access public
  77.      * @return Array
  78.      */
  79.  
  80.     function parseFile($file, $options = array())
  81.     {
  82.         $options = array_merge(array('debug' => false),$options);
  83.         if (!($tokens = $this->_tokenize($file))) {
  84.             return false;
  85.         }
  86.         return $this->_parseTokens($tokens,$options);
  87.     }
  88.  
  89.     /**
  90.      * Parse a string for its Compatibility info
  91.      *
  92.      * @param string $string PHP Code to parses
  93.      * @param array $options An array of options where:
  94.      *                          'debug' contains a boolean
  95.      *                              to control whether extra
  96.      *                              ouput is shown.
  97.      *                          'ignore_functions' contains an array
  98.      *                              of functions to ignore when
  99.      *                              calculating the version needed.
  100.      * @access public
  101.      * @return Array
  102.      */
  103.  
  104.     function  parseString($string, $options = array())
  105.     {
  106.         $options = array_merge(array('debug' => false),$options);
  107.         if (!($tokens = $this->_tokenize($string,true))) {
  108.             return false;
  109.         }
  110.         return $this->_parseTokens($tokens,$options);
  111.     }
  112.  
  113.     /**
  114.      * Parse a directory recursively for its Compatibility info
  115.      *
  116.      * @see PHP_CompatInfo::_fileList()
  117.      * @param string $dir Path of folder to parse
  118.      * @param array $options Array of user options where:
  119.      *                              'file_ext' Contains an array of file
  120.      *                                         extensions to parse for PHP
  121.      *                                         code. Default: php, php4,
  122.      *                                         inc, phtml
  123.      *                              'recurse_dir' Boolean on whether to
  124.      *                                         recursively find files
  125.      *                              'debug' contains a boolean
  126.      *                                         to control whether extra
  127.      *                                         ouput is shown.
  128.      *                              'ignore_files' contains an array of
  129.      *                                         files to ignore. File
  130.      *                                         names are case insensitive.
  131.      *                              'ignore_dirs' contains an array of
  132.      *                                         directories to ignore.
  133.      *                                         Directory names are case
  134.      *                                         insensitive.
  135.      *                          'ignore_functions' contains an array
  136.      *                                         of functions to ignore when
  137.      *                                         calculating the version needed.
  138.      * @access public
  139.      * @return array
  140.      */
  141.  
  142.     function parseDir($dir,$options = array())
  143.     {
  144.         $files = array();
  145.         $latest_version = $this->latest_version;
  146.         $extensions = array();
  147.         $constants = array();
  148.         $ignored = array();
  149.         $default_options = array('file_ext' => array('php','php4','inc','phtml'), 'recurse_dir' => true, 'debug' => false, 'ignore_files' => array(), 'ignore_dirs' => array());
  150.         $options = array_merge($default_options,$options);
  151.         
  152.         if(is_dir($dir) && is_readable($dir)) {
  153.             if($dir{strlen($dir)-1} == '/' || $dir{strlen($dir)-1} == '\\') {
  154.                 $dir = substr($dir,0,-1);
  155.             }
  156.             array_map('strtolower', $options['file_ext']);
  157.             array_map('strtolower', $options['ignore_files']);
  158.             array_map('strtolower', $options['ignore_dirs']);
  159.             $files_raw = $this->_fileList($dir,$options);
  160.             foreach($files_raw as $file) {
  161.                 if(in_array(strtolower($file),$options['ignore_files'])) {
  162.                     $ignored[] = $file;
  163.                     continue;
  164.                 }
  165.                 $file_info = pathinfo($file);
  166.                 if (isset($file_info['extension']) && in_array(strtolower($file_info['extension']),$options['file_ext'])) {
  167.                     $tokens = $this->_tokenize($file);
  168.                     if ($tokens != false) {
  169.                         $files[$file] = $this->_parseTokens($tokens,$options);
  170.                     } else {
  171.                         return false;
  172.                     }
  173.                 }
  174.             }
  175.             foreach($files as $file) {
  176.                 $cmp = version_compare($latest_version,$file['version']);
  177.                 if ((int)$cmp === -1) {
  178.                     $latest_version = $file['version'];
  179.                 }
  180.                 foreach($file['extensions'] as $ext) {
  181.                     if(!in_array($ext,$extensions)) {
  182.                         $extensions[] = $ext;
  183.                     }
  184.                 }
  185.                 foreach ($file['constants'] as $const) {
  186.                     if(!in_array($const,$constants)) {
  187.                         $constants[] = $const;
  188.                     }
  189.                 }
  190.             }
  191.  
  192.             if (sizeof($files) < 1) {
  193.                 return false;
  194.             }
  195.  
  196.             $files['constants'] = $constants;
  197.             $files['extensions'] = $extensions;
  198.             $files['version'] = $latest_version;
  199.             $files['ignored_files'] = $ignored;
  200.  
  201.             return array_reverse($files);
  202.         } else {
  203.             return false;
  204.         }
  205.     }
  206.  
  207.     /**
  208.      * Alias of parseDir
  209.      *
  210.      * @uses PHP_CompatInfo::parseDir()
  211.      * @access public
  212.      */
  213.  
  214.     function parseFolder($folder,$options = array()) {
  215.         return $this->parseDir($folder,$options);
  216.     }
  217.  
  218.     /**
  219.      * Parse an Array of Files
  220.      *
  221.      * You can parse an array of Files or Strings, to parse
  222.      * strings, $options['is_string'] must be set to true
  223.      *
  224.      * @param array $files Array of file names or code strings
  225.      * @param array $options An array of options where:
  226.      *                          'file_ext' Contains an array of file
  227.      *                              extensions to parse for PHP
  228.      *                              code. Default: php, php4,
  229.      *                              inc, phtml
  230.      *                          'debug' contains a boolean
  231.      *                              to control whether extra
  232.      *                              ouput is shown.
  233.      *                          'is_string' contains a boolean
  234.      *                              which says if the array values
  235.      *                              are strings or file names.
  236.      *                          'ignore_files' contains an array of
  237.      *                                          files to ignore. File
  238.      *                                          names are case sensitive.
  239.      *                          'ignore_functions' contains an array
  240.      *                                         of functions to ignore when
  241.      *                                         calculating the version needed.
  242.      * @access public
  243.      * @return array
  244.      */
  245.  
  246.     function parseArray($files,$options = array()) {
  247.         $latest_version = $this->latest_version;
  248.         $extensions = array();
  249.         $constants = array();
  250.         $options = array_merge(array('file_ext' => array('php','php4','inc','phtml'), 'is_string' => false,'debug' => false, 'ignore_files' => array()),$options);
  251.         $options['ignore_files'] = array_map("strtolower",$options['ignore_files']);
  252.         foreach($files as $file) {                
  253.             if ($options['is_string'] == false) {
  254.                 $pathinfo = pathinfo($file);
  255.                 if (!in_array(strtolower($file),$options['ignore_files']) && in_array($pathinfo['extension'],$options['file_ext'])) {
  256.                     $tokens = $this->_tokenize($file,$options['is_string']);
  257.                     if ($tokens != false) {
  258.                         $files_parsed[$file] = $this->_parseTokens($tokens,$options);
  259.                     } else {
  260.                         $files_parsed[$file] = false;
  261.                     }
  262.                 } else {
  263.                     $ignored[] = $file;
  264.                 }
  265.             } else {
  266.                 $tokens = $this->_tokenize($file,$options['is_string']);
  267.                 if ($tokens != false) {
  268.                     $files_parsed[] = $this->_parseTokens($tokens,$options);
  269.                 } else {
  270.                     $files_parsed[] = false;
  271.                 }
  272.             }
  273.         }
  274.  
  275.         foreach($files_parsed as $file) {
  276.             if ($file != false) {
  277.                 $cmp = version_compare($latest_version,$file['version']);
  278.                 if ((int)$cmp === -1) {
  279.                     $latest_version = $file['version'];
  280.                 }
  281.                 foreach($file['extensions'] as $ext) {
  282.                     if(!in_array($ext,$extensions)) {
  283.                         $extensions[] = $ext;
  284.                     }
  285.                 }
  286.                 foreach($file['constants'] as $const) {
  287.                     if(!in_array($const,$constants)) {
  288.                         $constants[] = $const;
  289.                     }
  290.                 }
  291.             }
  292.         }
  293.  
  294.         $files_parsed['constants'] = $constants;
  295.         $files_parsed['extensions'] = $extensions;
  296.         $files_parsed['version'] = $latest_version;
  297.         $files_parsed['ignored_files'] =  isset($ignored) ? $ignored : array();
  298.         return array_reverse($files_parsed);
  299.     }
  300.  
  301.     /**
  302.      * Parse the given Tokens
  303.      *
  304.      * The tokens are those returned by
  305.      * token_get_all() which is nicely
  306.      * wrapped in PHP_CompatInfo::_tokenize
  307.      *
  308.      * @param array $tokens Array of PHP Tokens
  309.      * @param boolean $debug Show Extra Output
  310.      * @access private
  311.      * @return array
  312.      */
  313.  
  314.     function _parseTokens($tokens, $options)
  315.     {
  316.         $functions = array();
  317.         $functions_version = array();
  318.         $latest_version = $this->latest_version;
  319.         $extensions = array();
  320.         $constants = array();
  321.         $constant_names = array();
  322.         $udf = array();
  323.         
  324.         /* Check for PHP 5 stuffs */
  325.         
  326.         $php5_tokens = @array(
  327.                         T_ABSTRACT => 'abstract',
  328.                         T_CATCH => 'catch',
  329.                         T_FINAL => 'final',
  330.                         T_INSTANCEOF => 'instanceof',
  331.                         T_PRIVATE => 'private',
  332.                         T_PROTECTED => 'protected',
  333.                         T_PUBLIC => 'public',
  334.                         T_THROW => 'throw',
  335.                         T_TRY => 'try',
  336.                         T_CLONE => 'clone',
  337.                         T_INTERFACE => 'interface',
  338.                         T_IMPLEMENTS => 'implements',
  339.                         );
  340.  
  341.         foreach ($php5_tokens as $php5_token => $value) {
  342.             if (in_array(array($php5_token, $value), $tokens) 
  343.                 || in_array(array($php5_token, strtoupper($value)), $tokens) 
  344.                 || in_array(array($php5_token, ucfirst($value)), $tokens)) {
  345.                 $constants[] = $php5_token;
  346.                 $latest_version = '5.0.0';
  347.                 break;
  348.             }
  349.         }
  350.         
  351.         $token_count = sizeof($tokens);
  352.         $i = 0;
  353.         while ($i < $token_count) {
  354.             $found_func = true;
  355.             if ($tokens[$i][0] == T_FUNCTION) {
  356.                 $found_func = false;
  357.             }
  358.             while ($found_func == false) {
  359.                 $i += 1;
  360.                 if ($tokens[$i][0] == T_STRING) {
  361.                     $found_func = true;
  362.                     $udf[] = $tokens[$i][1];
  363.                 }
  364.             }
  365.             if ($tokens[$i][0] == T_STRING) {
  366.                 if (isset($tokens[$i + 1]) && ($tokens[$i + 1][0] == '(') && ($tokens[$i - 1][0] != T_DOUBLE_COLON) && ($tokens[$i - 1][0] != T_OBJECT_OPERATOR)) {
  367.                     $functions[] = $tokens[$i][1];
  368.                 }
  369.             }
  370.             if (in_array($tokens[$i][0],$GLOBALS['const']['tokens'])) {
  371.                 $constants[] = $tokens[$i][0];
  372.             }
  373.             $i += 1;
  374.         }
  375.  
  376.         $functions = array_unique($functions);
  377.         if (isset($options['ignore_functions'])) {
  378.             $options['ignore_functions'] = array_map("strtolower",$options['ignore_functions']);
  379.         } else {
  380.             $options['ignore_functions'] = array();
  381.         }
  382.         foreach($functions as $name) {
  383.             if (isset($GLOBALS['funcs'][$name]) && (!in_array($name,$udf) && (!in_array($name,$options['ignore_functions'])))) {
  384.                 if ($options['debug'] == true) {
  385.                     $functions_version[$GLOBALS['funcs'][$name]['init']][] = array('function' => $name, 'extension' => $GLOBALS['funcs'][$name]['ext']);
  386.                 }
  387.                 $cmp = version_compare($latest_version,$GLOBALS['funcs'][$name]['init']);
  388.                 if ((int)$cmp === -1) {
  389.                     $latest_version = $GLOBALS['funcs'][$name]['init'];
  390.                 }
  391.                 if ((!empty($GLOBALS['funcs'][$name]['ext'])) && ($GLOBALS['funcs'][$name]['ext'] != 'ext_standard') && ($GLOBALS['funcs'][$name]['ext'] != 'zend'))  {
  392.                     $extension = substr($GLOBALS['funcs'][$name]['ext'],4);
  393.                     if ($extension{0} != '_') {
  394.                         if(!in_array($extension,$extensions)) {
  395.                             $extensions[] = $extension;
  396.                         }
  397.                     } else {
  398.                         $ext = substr($extension, 1);
  399.                         if(!in_array($extension,$extensions)) {
  400.                             $extensions[] = $extension;
  401.                         }
  402.                     }
  403.                 }
  404.             }
  405.         }
  406.  
  407.         $constants = array_unique($constants);
  408.         foreach($constants as $constant) {
  409.             $cmp = version_compare($latest_version,$GLOBALS['const'][$constant]['init']);
  410.             if ((int)$cmp === -1) {
  411.                 $latest_version = $GLOBALS['const'][$constant]['init'];
  412.             }
  413.             if(!in_array($GLOBALS['const'][$constant]['name'],$constant_names)) {
  414.                 $constant_names[] = $GLOBALS['const'][$constant]['name'];
  415.             }
  416.         }
  417.  
  418.         ksort($functions_version);
  419.  
  420.         $functions_version['constants'] = $constant_names;
  421.         $functions_version['extensions'] = $extensions;
  422.         $functions_version['version'] = $latest_version;
  423.         $functions_version = array_reverse($functions_version);
  424.         return $functions_version;
  425.     }
  426.  
  427.     /**
  428.      * Token a file or string
  429.      *
  430.      * @param string $input Filename or PHP code
  431.      * @param boolean $is_string Whether or note the input is a string
  432.      * @access private
  433.      * @return array
  434.      */
  435.  
  436.     function _tokenize($input,$is_string = false)
  437.     {
  438.         if ($is_string == false) {
  439.             $input = @file_get_contents($input,1);
  440.             if (is_string($input)) {
  441.                 return token_get_all($input);
  442.             }
  443.             return false;
  444.         } else {
  445.             return token_get_all($input);
  446.         }
  447.     }
  448.  
  449.     /**
  450.      * Retrieve a listing of every file in $directory and
  451.      * all subdirectories. Taken from PEAR_PackageFileManager_File
  452.      *
  453.      * @param string $directory full path to the directory you want the list of
  454.      * @access private
  455.      * @return array list of files in a directory
  456.      */
  457.  
  458.     function _fileList($directory,$options)
  459.     {
  460.         $ret = false;
  461.         if (@is_dir($directory) && (!in_array(strtolower($directory),$options['ignore_dirs']))) {
  462.             $ret = array();
  463.             $d = @dir($directory);
  464.             while($d && $entry=$d->read()) {
  465.                 if ($entry{0} != '.') {
  466.                     if (is_file($directory . DIRECTORY_SEPARATOR . $entry)) {
  467.                         $ret[] = $directory . DIRECTORY_SEPARATOR . $entry;
  468.                     }
  469.                     if (is_dir($directory . DIRECTORY_SEPARATOR . $entry) && ($options['recurse_dir'] != false)) {
  470.                         $tmp = $this->_fileList($directory . DIRECTORY_SEPARATOR . $entry,$options);
  471.                         if (is_array($tmp)) {
  472.                             foreach($tmp as $ent) {
  473.                                 $ret[] = $ent;
  474.                             }
  475.                         }
  476.                     }
  477.                 }
  478.             }
  479.             if ($d) {
  480.                 $d->close();
  481.             }
  482.         } else {
  483.             return false;
  484.         }
  485.  
  486.         return $ret;
  487.     }
  488. }
  489.  
  490. ?>