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

Source for file CompatInfo.php

Documentation is available at CompatInfo.php

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

Documentation generated on Thu, 22 Apr 2004 13:57:46 +0100 by phpDocumentor 1.3.0RC3