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

Documentation generated on Tue, 9 Mar 2004 18:21:04 +0000 by phpDocumentor 1.3.0RC2. PEAR Logo Copyright © PHP Group 2004.