/pear/php/PHP/CompatInfo/Parser.php
PHP | 1926 lines | 1625 code | 46 blank | 255 comment | 68 complexity | eaecdf9cd36876b82308ebfa9159b79e MD5 | raw file
Possible License(s): BSD-2-Clause, LGPL-2.1
Large files files are truncated, but you can click here to view the full file
- <?php
- /**
- * Copyright (c) 2008-2009, Davey Shafik <davey@php.net>
- * Laurent Laville <pear@laurent-laville.org>
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the authors nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * PHP versions 4 and 5
- *
- * @category PHP
- * @package PHP_CompatInfo
- * @author Davey Shafik <davey@php.net>
- * @author Laurent Laville <pear@laurent-laville.org>
- * @license http://www.opensource.org/licenses/bsd-license.php BSD
- * @version CVS: $Id: Parser.php,v 1.21 2009/01/02 10:18:47 farell Exp $
- * @link http://pear.php.net/package/PHP_CompatInfo
- * @since File available since Release 1.8.0b2
- */
-
- require_once 'Event/Dispatcher.php';
- require_once 'File/Find.php';
-
- /**
- * An array of class init versions and extension
- */
- require_once 'PHP/CompatInfo/class_array.php';
-
- /**
- * An array of function init versions and extension
- */
- require_once 'PHP/CompatInfo/func_array.php';
-
- /**
- * An array of constants and their init versions
- */
- require_once 'PHP/CompatInfo/const_array.php';
-
- /**
- * An abstract base class for CompatInfo renderers
- */
- require_once 'PHP/CompatInfo/Renderer.php';
-
- /**
- * Event name of parsing data source start process
- */
- define('PHP_COMPATINFO_EVENT_AUDITSTARTED', 'auditStarted');
- /**
- * Event name of parsing data source end process
- */
- define('PHP_COMPATINFO_EVENT_AUDITFINISHED', 'auditFinished');
- /**
- * Event name of parsing a file start process
- */
- define('PHP_COMPATINFO_EVENT_FILESTARTED', 'fileStarted');
- /**
- * Event name of parsing a file end process
- */
- define('PHP_COMPATINFO_EVENT_FILEFINISHED', 'fileFinished');
- /**
- * Event name of parsing a file start process
- */
- define('PHP_COMPATINFO_EVENT_CODESTARTED', 'codeStarted');
- /**
- * Event name of parsing a file end process
- */
- define('PHP_COMPATINFO_EVENT_CODEFINISHED', 'codeFinished');
-
- /**
- * Parser logic
- *
- * This class is the model in the MVC design pattern of API 1.8.0 (since beta 2)
- *
- * @category PHP
- * @package PHP_CompatInfo
- * @author Laurent Laville <pear@laurent-laville.org>
- * @license http://www.opensource.org/licenses/bsd-license.php BSD
- * @version Release: 1.9.0
- * @link http://pear.php.net/package/PHP_CompatInfo
- * @since Class available since Release 1.8.0b2
- */
- class PHP_CompatInfo_Parser
- {
- /**
- * Instance of concrete renderer used to show parse results
- *
- * @var object
- * @since 1.8.0b2
- * @access protected
- */
- var $renderer;
-
- /**
- * Stores the event dispatcher which handles notifications
- *
- * @var object
- * @since 1.8.0b2
- * @access protected
- */
- var $dispatcher;
-
- /**
- * Count the number of observer registered.
- * The Event_Dispatcher will be add on first observer registration, and
- * will be removed with the last observer.
- *
- * @var integer
- * @since 1.8.0b2
- * @access private
- */
- var $_observerCount;
-
- /**
- * @var string Earliest version of PHP to use
- * @since 0.7.0
- */
- var $latest_version = '4.0.0';
-
- /**
- * @var string Last version of PHP to use
- */
- var $earliest_version = '';
-
- /**
- * @var array Parsing options
- */
- var $options;
-
- /**
- * @var array Data Source
- * @since 1.8.0b2
- */
- var $dataSource;
-
- /**
- * @var array Directory list found when parsing data source
- * @since 1.8.0b2
- * @see getDirlist()
- */
- var $directories;
-
- /**
- * @var array List of files ignored when parsing data source
- * @since 1.8.0b2
- * @see getIgnoredFiles()
- */
- var $ignored_files = array();
-
- /**
- * @var array Result of the latest data source parsing
- * @since 1.9.0b1
- * @see parseData()
- */
- var $latest_parse = null;
-
- /**
- * Class constructor (ZE1) for PHP4
- *
- * @access public
- * @since version 1.8.0b2 (2008-06-03)
- */
- function PHP_CompatInfo_Parser()
- {
- $this->__construct();
- }
-
- /**
- * Class constructor (ZE2) for PHP5+
- *
- * @access public
- * @since version 1.8.0b2 (2008-06-03)
- */
- function __construct()
- {
- $this->options = array(
- 'file_ext' => array('php', 'php4', 'inc', 'phtml'),
- 'recurse_dir' => true,
- 'debug' => false,
- 'is_string' => false,
- 'ignore_files' => array(),
- 'ignore_dirs' => array()
- );
- }
-
- /**
- * Set up driver to be used
- *
- * Set up driver to be used, dependant on specified type.
- *
- * @param string $type Name the type of driver (html, text...)
- * @param array $conf A hash containing any additional configuration
- *
- * @access public
- * @return void
- * @since version 1.8.0b2 (2008-06-03)
- */
- function setOutputDriver($type, $conf = array())
- {
- $this->renderer =& PHP_CompatInfo_Renderer::factory($this, $type, $conf);
- }
-
- /**
- * Registers a new listener
- *
- * Registers a new listener with the given criteria.
- *
- * @param mixed $callback A PHP callback
- * @param string $nName (optional) Expected notification name
- *
- * @access public
- * @return void
- * @since version 1.8.0b2 (2008-06-03)
- */
- function addListener($callback, $nName = EVENT_DISPATCHER_GLOBAL)
- {
- $this->dispatcher =& Event_Dispatcher::getInstance();
- // $this->dispatcher->setNotificationClass('PHP_CompatInfo_Audit');
- $this->dispatcher->addObserver($callback, $nName);
- $this->_observerCount++;
- }
-
- /**
- * Removes a registered listener
- *
- * Removes a registered listener that correspond to the given criteria.
- *
- * @param mixed $callback A PHP callback
- * @param string $nName (optional) Expected notification name
- *
- * @access public
- * @return bool True if listener was removed, false otherwise.
- * @since version 1.8.0b2 (2008-06-03)
- */
- function removeListener($callback, $nName = EVENT_DISPATCHER_GLOBAL)
- {
- $result = $this->dispatcher->removeObserver($callback, $nName);
-
- if ($result) {
- $this->_observerCount--;
- if ($this->_observerCount == 0) {
- unset($this->dispatcher);
- }
- }
- return $result;
- }
-
- /**
- * Post a new notification to all listeners registered.
- *
- * This notification occured only if a dispatcher exists. That means if
- * at least one listener was registered.
- *
- * @param string $event Name of the notification handler
- * @param array $info (optional) Additional information about the notification
- *
- * @access public
- * @return void
- * @since version 1.8.0b2 (2008-06-03)
- */
- function notifyListeners($event, $info = array())
- {
- if (isset($this->dispatcher)) {
- $this->dispatcher->post($this, $event, $info);
- }
- }
-
- /**
- * Load components list
- *
- * Load components list for a PHP version or subset
- *
- * @param string $min PHP minimal version
- * @param string|boolean $max (optional) PHP maximal version
- * @param boolean $include_const (optional) include constants list
- * in final result
- * @param boolean $groupby_vers (optional) give initial php version
- * of function or constant
- *
- * @return array An array of php function/constant names history
- * @access public
- * @static
- * @since version 1.2.0 (2006-08-23)
- */
- function loadVersion($min, $max = false,
- $include_const = false, $groupby_vers = false)
- {
- $keys = array();
- foreach ($GLOBALS['_PHP_COMPATINFO_FUNCS'] as $func => $arr) {
- if (isset($arr['pecl']) && $arr['pecl'] === true) {
- continue;
- }
- $vmin = $arr['init'];
- if (version_compare($vmin, $min) < 0) {
- continue;
- }
- if ($max) {
- $end = (isset($arr['end'])) ? $arr['end'] : $vmin;
-
- if (version_compare($end, $max) < 1) {
- if ($groupby_vers === true) {
- $keys[$vmin][] = $func;
- } else {
- $keys[] = $func;
- }
- }
- } else {
- if ($groupby_vers === true) {
- $keys[$vmin][] = $func;
- } else {
- $keys[] = $func;
- }
- }
- }
- if ($groupby_vers === true) {
- foreach ($keys as $vmin => $func) {
- sort($keys[$vmin]);
- }
- ksort($keys);
- } else {
- sort($keys);
- }
-
- if ($include_const === true) {
- $keys = array('functions' => $keys, 'constants' => array());
- foreach ($GLOBALS['_PHP_COMPATINFO_CONST'] as $const => $arr) {
- $vmin = $arr['init'];
- if (version_compare($vmin, $min) < 0) {
- continue;
- }
- if ($max) {
- $end = (isset($arr['end'])) ? $arr['end'] : $vmin;
-
- if (version_compare($end, $max) < 1) {
- if ($groupby_vers === true) {
- $keys['constants'][$vmin][] = $arr['name'];
- } else {
- $keys['constants'][] = $arr['name'];
- }
- }
- } else {
- if ($groupby_vers === true) {
- $keys['constants'][$vmin][] = $arr['name'];
- } else {
- $keys['constants'][] = $arr['name'];
- }
- }
- }
- ksort($keys['constants']);
- }
- return $keys;
- }
-
- /**
- * Returns list of directory parsed
- *
- * Returns list of directory parsed, depending of restrictive parser options.
- *
- * @param mixed $dir The directory name
- * @param array $options An array of parser options. See parseData() method.
- *
- * @access public
- * @return array list of directories that should be parsed
- * @since version 1.8.0b2 (2008-06-03)
- */
- function getDirlist($dir, $options)
- {
- if (!isset($this->directories)) {
- $this->getFilelist($dir, $options);
- }
-
- return $this->directories;
- }
-
- /**
- * Returns list of files parsed
- *
- * Returns list of files parsed, depending of restrictive parser options.
- *
- * @param mixed $dir The directory name where to look files
- * @param array $options An array of parser options. See parseData() method.
- *
- * @access public
- * @return array list of files that should be parsed
- * @since version 1.8.0b2 (2008-06-03)
- */
- function getFilelist($dir, $options)
- {
- $skipped = array();
- $ignored = array();
-
- $options = array_merge($this->options, $options);
- $options['file_ext'] = array_map('strtolower', $options['file_ext']);
-
- if ($dir{strlen($dir)-1} == '/' || $dir{strlen($dir)-1} == '\\') {
- $dir = substr($dir, 0, -1);
- }
-
- // use system directory separator rather than forward slash by default
- $ff = new File_Find();
- $ff->dirsep = DIRECTORY_SEPARATOR;
-
- // get directory list that should be ignored from scope
- $ignore_dirs = array();
- if (count($options['ignore_dirs']) > 0) {
- foreach ($options['ignore_dirs'] as $cond) {
- $cond = str_replace('\\', "\\\\", $cond);
- $dirs = $ff->search('`'.$cond.'`', $dir, 'perl',
- true, 'directories');
- $ignore_dirs = array_merge($ignore_dirs, $dirs);
- }
- }
-
- // get file list that should be ignored from scope
- $ignore_files = array();
- if (count($options['ignore_files']) > 0) {
- foreach ($options['ignore_files'] as $cond) {
- $cond = str_replace('\\', "\\\\", $cond);
- $files = $ff->search('`'.$cond.'`', $dir, 'perl',
- true, 'files');
- $ignore_files = array_merge($ignore_files, $files);
- }
- }
-
- list($directories, $files) = $ff->maptree($dir);
-
- foreach ($files as $file) {
-
- $file_info = pathinfo($file);
- if ($options['recurse_dir'] == false
- && $file_info['dirname'] != $dir) {
- $skipped[] = $file;
- continue;
- }
- if (in_array($file_info['dirname'], $ignore_dirs)) {
- $ignored[] = $file;
-
- } elseif (in_array($file, $ignore_files)) {
- $ignored[] = $file;
-
- } else {
- if (isset($file_info['extension'])
- && in_array(strtolower($file_info['extension']),
- $options['file_ext'])) {
- continue;
- }
- $ignored[] = $file;
- }
- }
-
- $files = PHP_CompatInfo_Parser::_arrayDiff($files,
- array_merge($ignored, $skipped));
- $this->directories
- = PHP_CompatInfo_Parser::_arrayDiff($directories, $ignore_dirs);
- $this->ignored_files
- = $ignored;
-
- return $files;
- }
-
- /**
- * Returns list of files ignored
- *
- * Returns list of files ignored while parsing directories
- *
- * @access public
- * @return array or false on error
- * @since version 1.8.0b2 (2008-06-03)
- */
- function getIgnoredFiles()
- {
- return $this->ignored_files;
- }
-
- /**
- * Returns the latest parse data source ignored functions
- *
- * Returns the latest parse data source ignored functions list
- *
- * @param mixed $file (optional) A specific filename or not (false)
- *
- * @access public
- * @return mixed Null on error or if there were no previous data parsing
- * @since version 1.9.0b2 (2008-12-19)
- */
- function getIgnoredFunctions($file = false)
- {
- if (!is_array($this->latest_parse)) {
- // no code analysis found
- $functions = null;
- } elseif ($file === false) {
- $functions = $this->latest_parse['ignored_functions'];
- } elseif (isset($this->latest_parse[$file])) {
- $functions = $this->latest_parse[$file]['ignored_functions'];
- } else {
- $functions = null;
- }
-
- return $functions;
- }
-
- /**
- * Returns the latest parse data source ignored extensions
- *
- * Returns the latest parse data source ignored extensions list
- *
- * @param mixed $file (optional) A specific filename or not (false)
- *
- * @access public
- * @return mixed Null on error or if there were no previous data parsing
- * @since version 1.9.0b2 (2008-12-19)
- */
- function getIgnoredExtensions($file = false)
- {
- if (!is_array($this->latest_parse)) {
- // no code analysis found
- $extensions = null;
- } elseif ($file === false) {
- $extensions = $this->latest_parse['ignored_extensions'];
- } elseif (isset($this->latest_parse[$file])) {
- $extensions = $this->latest_parse[$file]['ignored_extensions'];
- } else {
- $extensions = null;
- }
-
- return $extensions;
- }
-
- /**
- * Returns the latest parse data source ignored constants
- *
- * Returns the latest parse data source ignored constants list
- *
- * @param mixed $file (optional) A specific filename or not (false)
- *
- * @access public
- * @return mixed Null on error or if there were no previous data parsing
- * @since version 1.9.0b2 (2008-12-19)
- */
- function getIgnoredConstants($file = false)
- {
- if (!is_array($this->latest_parse)) {
- // no code analysis found
- $constants = null;
- } elseif ($file === false) {
- $constants = $this->latest_parse['ignored_constants'];
- } elseif (isset($this->latest_parse[$file])) {
- $constants = $this->latest_parse[$file]['ignored_constants'];
- } else {
- $constants = null;
- }
-
- return $constants;
- }
-
- /**
- * Returns the latest parse data source version
- *
- * Returns the latest parse data source version, minimum and/or maximum
- *
- * @param mixed $file (optional) A specific filename or not (false)
- * @param bool $max (optional) Level with or without contextual data
- *
- * @access public
- * @return mixed Null on error or if there were no previous data parsing
- * @since version 1.9.0b1 (2008-11-30)
- */
- function getVersion($file = false, $max = false)
- {
- $key = ($max === true) ? 'max_version' : 'version';
-
- if (!is_array($this->latest_parse)) {
- // no code analysis found
- $version = null;
- } elseif ($file === false) {
- $version = $this->latest_parse[$key];
- } elseif (isset($this->latest_parse[$file])) {
- $version = $this->latest_parse[$file][$key];
- } else {
- $version = null;
- }
-
- return $version;
- }
-
- /**
- * Returns the latest parse data source classes declared
- *
- * Returns the latest parse data source classes declared (internal or
- * end-user defined)
- *
- * @param mixed $file (optional) A specific filename or not (false)
- *
- * @access public
- * @return mixed Null on error or if there were no previous data parsing
- * @since version 1.9.0b1 (2008-11-30)
- */
- function getClasses($file = false)
- {
- if (!is_array($this->latest_parse)) {
- // no code analysis found
- $classes = null;
- } elseif ($file === false) {
- $classes = $this->latest_parse['classes'];
- } elseif (isset($this->latest_parse[$file])) {
- $classes = $this->latest_parse[$file]['classes'];
- } else {
- $classes = null;
- }
-
- return $classes;
- }
-
- /**
- * Returns the latest parse data source functions declared
- *
- * Returns the latest parse data source functions declared (internal or
- * end-user defined)
- *
- * @param mixed $file (optional) A specific filename or not (false)
- *
- * @access public
- * @return mixed Null on error or if there were no previous data parsing
- * @since version 1.9.0b1 (2008-11-30)
- */
- function getFunctions($file = false)
- {
- if (!is_array($this->latest_parse)) {
- // no code analysis found
- $functions = null;
- } elseif ($file === false) {
- $functions = $this->latest_parse['functions'];
- } elseif (isset($this->latest_parse[$file])) {
- $functions = $this->latest_parse[$file]['functions'];
- } else {
- $functions = null;
- }
-
- return $functions;
- }
-
- /**
- * Returns the latest parse data source extensions used
- *
- * Returns the latest parse data source extensions used
- *
- * @param mixed $file (optional) A specific filename or not (false)
- *
- * @access public
- * @return mixed Null on error or if there were no previous data parsing
- * @since version 1.9.0b1 (2008-11-30)
- */
- function getExtensions($file = false)
- {
- if (!is_array($this->latest_parse)) {
- // no code analysis found
- $extensions = null;
- } elseif ($file === false) {
- $extensions = $this->latest_parse['extensions'];
- } elseif (isset($this->latest_parse[$file])) {
- $extensions = $this->latest_parse[$file]['extensions'];
- } else {
- $extensions = null;
- }
-
- return $extensions;
- }
-
- /**
- * Returns the latest parse data source constants declared
- *
- * Returns the latest parse data source constants declared (internal or
- * end-user defined)
- *
- * @param mixed $file (optional) A specific filename or not (false)
- *
- * @access public
- * @return mixed Null on error or if there were no previous data parsing
- * @since version 1.9.0b1 (2008-11-30)
- */
- function getConstants($file = false)
- {
- if (!is_array($this->latest_parse)) {
- // no code analysis found
- $constants = null;
- } elseif ($file === false) {
- $constants = $this->latest_parse['constants'];
- } elseif (isset($this->latest_parse[$file])) {
- $constants = $this->latest_parse[$file]['constants'];
- } else {
- $constants = null;
- }
-
- return $constants;
- }
-
- /**
- * Returns the latest parse data source tokens declared
- *
- * Returns the latest parse data source PHP5+ tokens declared
- *
- * @param mixed $file (optional) A specific filename or not (false)
- *
- * @access public
- * @return mixed Null on error or if there were no previous data parsing
- * @since version 1.9.0b1 (2008-11-30)
- */
- function getTokens($file = false)
- {
- if (!is_array($this->latest_parse)) {
- // no code analysis found
- } elseif ($file === false) {
- $tokens = $this->latest_parse['tokens'];
- } elseif (isset($this->latest_parse[$file])) {
- $tokens = $this->latest_parse[$file]['tokens'];
- } else {
- $tokens = null;
- }
-
- return $tokens;
- }
-
- /**
- * Returns the latest parse data source conditions
- *
- * Returns the latest parse data source conditions, with or without
- * contextual data
- *
- * @param mixed $file (optional) A specific filename or not (false)
- * @param bool $levelOnly (optional) Level with or without contextual data
- *
- * @access public
- * @return mixed Null on error or if there were no previous data parsing
- * @since version 1.9.0b1 (2008-11-30)
- */
- function getConditions($file = false, $levelOnly = false)
- {
- if (!is_array($this->latest_parse)) {
- // no code analysis found
- $conditions = null;
- } elseif ($file === false) {
- $conditions = $this->latest_parse['cond_code'];
- } elseif (isset($this->latest_parse[$file])) {
- $conditions = $this->latest_parse[$file]['cond_code'];
- } else {
- $conditions = null;
- }
-
- if (is_array($conditions) && $levelOnly === true) {
- $conditions = $conditions[0];
- }
- return $conditions;
- }
-
- /**
- * Parse a data source
- *
- * Parse a data source with auto detect ability. This data source, may be
- * one of these follows: a directory, a file, a string (chunk of code),
- * an array of multiple origin.
- *
- * Each of five parsing functions support common and specifics options.
- *
- * * Common options :
- * - 'debug' Contains a boolean to control whether
- * extra ouput is shown.
- * - 'ignore_functions' Contains an array of functions to ignore
- * when calculating the version needed.
- * - 'ignore_constants' Contains an array of constants to ignore
- * when calculating the version needed.
- * - 'ignore_extensions' Contains an array of php extensions to ignore
- * when calculating the version needed.
- * - 'ignore_versions' Contains an array of php versions to ignore
- * when calculating the version needed.
- * - 'ignore_functions_match' Contains an array of function patterns to ignore
- * when calculating the version needed.
- * - 'ignore_extensions_match' Contains an array of extension patterns to ignore
- * when calculating the version needed.
- * - 'ignore_constants_match' Contains an array of constant patterns to ignore
- * when calculating the version needed.
- *
- * * parseArray, parseDir|parseFolder, specific options :
- * - 'file_ext' Contains an array of file extensions to parse
- * for PHP code. Default: php, php4, inc, phtml
- * - 'ignore_files' Contains an array of files to ignore.
- * File names are case insensitive.
- *
- * * parseArray specific options :
- * - 'is_string' Contains a boolean which says if the array values
- * are strings or file names.
- *
- * * parseDir|parseFolder specific options :
- * - 'recurse_dir' Boolean on whether to recursively find files
- * - 'ignore_dirs' Contains an array of directories to ignore.
- * Directory names are case insensitive.
- *
- * @param mixed $dataSource The data source (may be file, dir, string, or array)
- * @param array $options An array of options. See above.
- *
- * @access public
- * @return array or false on error
- * @since version 1.8.0b2 (2008-06-03)
- */
- function parseData($dataSource, $options = array())
- {
- $this->options = array_merge($this->options, $options);
-
- $dataType = gettype($dataSource);
- $dataCount = 0;
- // - when array source with mixed content incompatible
- // - if all directories are not readable
- // - if data source invalid type: other than file, directory, string
-
- if ($dataType == 'string' || $dataType == 'array') {
- if (is_array($dataSource)) {
- //$dataType = 'array';
- } elseif (is_dir($dataSource)) {
- $dataType = 'directory';
- $dataSource = array($dataSource);
- } elseif (is_file($dataSource)) {
- $dataType = 'file';
- $dataSource = array($dataSource);
- } elseif (substr($dataSource, 0, 5) == '<?php') {
- //$dataType = 'string';
- $this->options = array_merge($this->options,
- array('is_string' => true));
- $dataSource = array($dataSource);
- } else {
- //$dataType = 'string';
- // directory or file are misspelled
- }
- if (is_array($dataSource)) {
- $dataSource = $this->_validateDataSource($dataSource,
- $this->options);
- $dataCount = count($dataSource);
- }
- }
-
- $this->dataSource = array('dataSource' => $dataSource,
- 'dataType' => $dataType,
- 'dataCount' => $dataCount);
-
- $eventInfo = array_merge($this->dataSource,
- array('parseOptions' => $this->options));
-
- // notify all observers that parsing data source begin
- $this->notifyListeners(PHP_COMPATINFO_EVENT_AUDITSTARTED, $eventInfo);
-
- if ($dataCount == 0) {
- $parseData = false;
- } else {
- switch ($dataType) {
- case 'array' :
- $parseData = $this->_parseArray($dataSource, $this->options);
- break;
- case 'string' :
- $parseData = $this->_parseString($dataSource, $this->options);
- break;
- case 'file' :
- $parseData = $this->_parseFile($dataSource, $this->options);
- break;
- case 'directory' :
- $parseData = $this->_parseDir($dataSource, $this->options);
- break;
- }
- }
-
- // notify all observers that parsing data source is over
- $this->notifyListeners(PHP_COMPATINFO_EVENT_AUDITFINISHED, $parseData);
-
- $this->latest_parse = $parseData;
- return $parseData;
- }
-
- /**
- * Validate content of data source
- *
- * Validate content of data source list, before parsing each source
- *
- * @param mixed $dataSource The data source (may be file, dir, or string)
- * @param array $options Parser options (see parseData() method for details)
- *
- * @access private
- * @return array empty array on error
- * @since version 1.8.0b3 (2008-06-07)
- */
- function _validateDataSource($dataSource, $options = array())
- {
- /**
- * Array by default expect to contains list of files and/or directories.
- * If you want a list of chunk of code (strings), 'is_string' option
- * must be set to true.
- */
- $list = array();
-
- foreach ($dataSource as $source) {
- if ($options['is_string'] === true) {
- if (is_string($source)) {
- $list[] = $source;
- } else {
- /**
- * One of items is not a string (chunk of code). All
- * data sources parsing are stopped and considered as invalid.
- */
- $list = array();
- break;
- }
- } else {
- if (is_dir($source) && is_readable($source)) {
- $files = $this->getFilelist($source, $options);
- $list = array_merge($list, $files);
- } elseif (is_file($source)) {
- $list[] = $source;
- } else {
- /**
- * One of items is not a valid file or directory. All
- * data sources parsing are stopped and considered as invalid.
- */
- $list = array();
- break;
- }
- }
- }
-
- return $list;
- }
-
- /**
- * Parse an Array of Files
- *
- * You can parse an array of Files or Strings, to parse
- * strings, $options['is_string'] must be set to true
- *
- * @param array $dataSource Array of file &| directory names or code strings
- * @param array $options Parser options (see parseData() method for details)
- *
- * @access private
- * @return array or false on error
- * @since version 0.7.0 (2004-03-09)
- * @see parseData()
- */
- function _parseArray($dataSource, $options = array())
- {
- // Each data source have been checked before (see _validateDataSource() )
- if (is_file($dataSource[0])) {
- $parseData = $this->_parseDir($dataSource, $options);
- } else {
- $parseData = $this->_parseString($dataSource, $options);
- }
-
- return $parseData;
- }
-
- /**
- * Parse a string
- *
- * Parse a string for its compatibility info.
- *
- * @param array $strings PHP Code to parse
- * @param array $options Parser options (see parseData() method for details)
- *
- * @access private
- * @return array or false on error
- * @since version 0.7.0 (2004-03-09)
- * @see parseData()
- */
- function _parseString($strings, $options = array())
- {
- $results = $this->_parseElements($strings, $options);
- return $results;
- }
-
- /**
- * Parse a single file
- *
- * Parse a single file for its compatibility info.
- *
- * @param string $file File to parse
- * @param array $options Parser options (see parseData() method for details)
- *
- * @access private
- * @return array or false on error
- * @since version 0.7.0 (2004-03-09)
- * @see parseData()
- */
- function _parseFile($file, $options = array())
- {
- $results = $this->_parseElements($file, $options);
- return $results;
- }
-
- /**
- * Parse a directory
- *
- * Parse a directory recursively for its compatibility info
- *
- * @param array $files Files list of folder to parse
- * @param array $options Parser options (see parseData() method for details)
- *
- * @access private
- * @return array or false on error
- * @since version 0.8.0 (2004-04-22)
- * @see parseData()
- */
- function _parseDir($files, $options = array())
- {
- $results = $this->_parseElements($files, $options);
- return $results;
- }
-
- /**
- * Parse a list of elements
- *
- * Parse a list of directory|file elements, or chunk of code (strings)
- *
- * @param array $elements Array of file &| directory names or code strings
- * @param array $options Parser options (see parseData() method for details)
- *
- * @access private
- * @return array
- * @since version 1.8.0b3 (2008-06-07)
- * @see _parseString(), _parseDir()
- */
- function _parseElements($elements, $options = array())
- {
- $files_parsed = array();
- $latest_version = $this->latest_version;
- $earliest_version = $this->earliest_version;
- $all_functions = array();
- $classes = array();
- $functions = array();
- $extensions = array();
- $constants = array();
- $tokens = array();
- $ignored_functions = array();
- $ignored_extensions = array();
- $ignored_constants = array();
- $function_exists = array();
- $extension_loaded = array();
- $defined = array();
- $cond_code = 0;
-
- foreach ($elements as $p => $element) {
- $index = $p + 1;
- if (is_file($element)) {
- if (in_array($element, $options['ignore_files'])) {
- $this->ignored_files[] = $element;
- continue;
- }
- $eventInfo
- = array('filename' => $element, 'fileindex' => $index);
- $this->notifyListeners(PHP_COMPATINFO_EVENT_FILESTARTED, $eventInfo);
-
- $tokens_list = $this->_tokenize($element);
- $kfile = $element;
- $files_parsed[$kfile] = $this->_parseTokens($tokens_list, $options);
-
- $this->notifyListeners(PHP_COMPATINFO_EVENT_FILEFINISHED);
- } else {
- $eventInfo
- = array('stringdata' => $element, 'stringindex' => $index);
- $this->notifyListeners(PHP_COMPATINFO_EVENT_CODESTARTED, $eventInfo);
-
- $tokens_list = $this->_tokenize($element, true);
- $kfile = 'string_' . $index;
- $files_parsed[$kfile] = $this->_parseTokens($tokens_list, $options);
-
- $this->notifyListeners(PHP_COMPATINFO_EVENT_CODEFINISHED);
- }
- }
-
- foreach ($files_parsed as $fn => $file) {
- $cmp = version_compare($latest_version, $file['version']);
- if ($cmp === -1) {
- $latest_version = $file['version'];
- }
- if ($file['max_version'] != '') {
- $cmp = version_compare($earliest_version, $file['max_version']);
- if ($earliest_version == '' || $cmp === 1) {
- $earliest_version = $file['max_version'];
- }
- }
- foreach ($file['classes'] as $class) {
- if (!in_array($class, $classes)) {
- $classes[] = $class;
- }
- }
- foreach ($file['functions'] as $func) {
- if (!in_array($func, $functions)) {
- $functions[] = $func;
- }
- }
- foreach ($file['extensions'] as $ext) {
- if (!in_array($ext, $extensions)) {
- $extensions[] = $ext;
- }
- }
- foreach ($file['constants'] as $const) {
- if (!in_array($const, $constants)) {
- $constants[] = $const;
- }
- }
- foreach ($file['tokens'] as $token) {
- if (!in_array($token, $tokens)) {
- $tokens[] = $token;
- }
- }
- foreach ($file['ignored_functions'] as $if) {
- if (!in_array($if, $ignored_functions)) {
- $ignored_functions[] = $if;
- }
- }
- foreach ($file['ignored_extensions'] as $ie) {
- if (!in_array($ie, $ignored_extensions)) {
- $ignored_extensions[] = $ie;
- }
- }
- foreach ($file['ignored_constants'] as $ic) {
- if (!in_array($ic, $ignored_constants)) {
- $ignored_constants[] = $ic;
- }
- }
- foreach ($file['cond_code'][1][0] as $ccf) {
- if (!in_array($ccf, $function_exists)) {
- $function_exists[] = $ccf;
- }
- }
- foreach ($file['cond_code'][1][1] as $cce) {
- if (!in_array($cce, $extension_loaded)) {
- $extension_loaded[] = $cce;
- }
- }
- foreach ($file['cond_code'][1][2] as $ccc) {
- if (!in_array($ccc, $defined)) {
- $defined[] = $ccc;
- }
- }
- if ($options['debug'] === false) {
- unset($files_parsed[$fn]['cond_code'][1]);
- } else {
- unset($file['ignored_functions']);
- unset($file['ignored_extensions']);
- unset($file['ignored_constants']);
- unset($file['max_version']);
- unset($file['version']);
- unset($file['classes']);
- unset($file['functions']);
- unset($file['extensions']);
- unset($file['constants']);
- unset($file['tokens']);
- unset($file['cond_code']);
-
- foreach ($file as $version => $file_functions) {
- // extra information available only when debug mode is on
- if (isset($all_functions[$version])) {
- foreach ($file_functions as $func) {
- $k = array_search($func, $all_functions[$version]);
- if ($k === false) {
- $all_functions[$version][] = $func;
- }
- }
- } else {
- $all_functions[$version] = $file_functions;
- }
- }
- }
- }
-
- if (count($files_parsed) == 0) {
- return false;
- }
-
- if (count($function_exists) > 0) {
- $cond_code += 1;
- }
- if (count($extension_loaded) > 0) {
- $cond_code += 2;
- }
- if (count($defined) > 0) {
- $cond_code += 4;
- }
- if ($options['debug'] === false) {
- $cond_code = array($cond_code);
- } else {
- sort($function_exists);
- sort($extension_loaded);
- sort($defined);
- $cond_code = array($cond_code, array($function_exists,
- $extension_loaded,
- $defined));
- }
-
- sort($ignored_functions);
- sort($ignored_extensions);
- sort($ignored_constants);
- sort($classes);
- sort($functions);
- natcasesort($extensions);
- sort($constants);
- sort($tokens);
- $main_info = array('ignored_files' => $this->getIgnoredFiles(),
- 'ignored_functions' => $ignored_functions,
- 'ignored_extensions' => $ignored_extensions,
- 'ignored_constants' => $ignored_constants,
- 'max_version' => $earliest_version,
- 'version' => $latest_version,
- 'classes' => $classes,
- 'functions' => $functions,
- 'extensions' => array_values($extensions),
- 'constants' => $constants,
- 'tokens' => $tokens,
- 'cond_code' => $cond_code);
-
- if (count($files_parsed) == 1) {
- if ($options['debug'] === false) {
- $parseData = $main_info;
- } else {
- $main_info = array('ignored_files' => $this->getIgnoredFiles());
- $parseData = array_merge($main_info,
- $files_parsed[$kfile], $all_functions);
- }
- } else {
- if ($options['debug'] === false) {
- $parseData = array_merge($main_info, $files_parsed);
- } else {
- $parseData = array_merge($main_info, $all_functions, $files_parsed);
- }
- }
-
- $this->notifyListeners(PHP_COMPATINFO_EVENT_FILEFINISHED, $parseData);
- return $parseData;
- }
-
- /**
- * Token a file or string
- *
- * @param string $input Filename or PHP code
- * @param boolean $is_string Whether or note the input is a string
- * @param boolean $debug add token names for human read
- *
- * @access private
- * @return array
- * @since version 0.7.0 (2004-03-09)
- */
- function _tokenize($input, $is_string = false, $debug = false)
- {
- if ($is_string === false) {
- $input = file_get_contents($input, true);
- }
- $tokens = token_get_all($input);
-
- if ($debug === true) {
- $r = array();
- foreach ($tokens as $token) {
- if (is_array($token)) {
- $token[] = token_name($token[0]);
- } else {
- $token = $token[0];
- }
- $r[] = $token;
- }
- } else {
- $r = $tokens;
- }
- return $r;
- }
-
- /**
- * Parse the given Tokens
- *
- * The tokens are those returned by token_get_all() which is nicely
- * wrapped in PHP_CompatInfo::_tokenize
- *
- * @param array $tokens Array of PHP Tokens
- * @param boolean $options Show Extra Output
- *
- * @access private
- * @return array
- * @since version 0.7.0 (2004-03-09)
- */
- function _parseTokens($tokens, $options)
- {
- static $akeys;
-
- $classes = array();
- $functions = array();
- $functions_version = array();
- $latest_version = $this->latest_version;
- $earliest_version = $this->earliest_version;
- $extensions = array();
- $constants = array();
- $constant_names = array();
- $token_names = array();
- $udf = array();
- $ignore_functions = array();
- $ignored_functions = array();
- $ignore_extensions = array();
- $ignored_extensions = array();
- $ignore_constants = array();
- $ignored_constants = array();
- $function_exists = array();
- $extension_loaded = array();
- $defined = array();
- $cond_code = 0;
-
- if (isset($options['ignore_constants'])) {
- $options['ignore_constants']
- = array_map('strtoupper', $options['ignore_constants']);
- } else {
- $options['ignore_constants'] = array();
- }
- if (isset($options['ignore_extensions'])) {
- $options['ignore_extensions']
- = array_map('strtolower', $options['ignore_extensions']);
- } else {
- $options['ignore_extensions'] = array();
- }
- if (isset($options['ignore_versions'][0])) {
- $min_ver = $options['ignore_versions'][0];
- } else {
- $min_ver = false;
- }
- if (isset($options['ignore_versions'][1])) {
- $max_ver = $options['ignore_versions'][1];
- } else {
- $max_ver = false;
- }
-
- if (isset($options['ignore_functions_match'])) {
- list($ifm_compare, $ifm_patterns) = $options['ignore_functions_match'];
- } else {
- $ifm_compare = false;
- }
- if (isset($options['ignore_extensions_match'])) {
- list($iem_compare, $iem_patterns) = $options['ignore_extensions_match'];
- } else {
- $iem_compare = false;
- }
- if (isset($options['ignore_constants_match'])) {
- list($icm_compare, $icm_patterns) = $options['ignore_constants_match'];
- } else {
- $icm_compare = false;
- }
-
- $token_count = sizeof($tokens);
- $i = 0;
- $found_class = false;
- while ($i < $token_count) {
- if ($this->_isToken($tokens[$i], 'T_FUNCTION')) {
- $found_func = false;
- } else {
- $found_func = true;
- }
- while ($found_func == false) {
- $i += 1;
- if ($this->_isToken($tokens[$i], 'T_STRING')) {
- $found_func = true;
- $func = $tokens[$i][1];
- if ($found_class === false
- || in_array($func, $function_exists)) {
- $udf[] = $func;
- }
- }
- }
-
- // Try to detect PHP method chaining implementation
- if ($this->_isToken($tokens[$i], 'T_VARIABLE')
- && $this->_isToken($tokens[$i+1], 'T_OBJECT_OPERATOR')
- && $this->_isToken($tokens[$i+2], 'T_STRING')
- && $this->_isToken($tokens[$i+3], '(')) {
-
- $i += 3;
- $php5_method_chaining = false;
- while (((!is_array($tokens[$i]) && $tokens[$i] == ';') === false)
- && (!$this->_isToken($tokens[$i], 'T_CLOSE_TAG'))
- ) {
- $i += 1;
- if ((($this->_isToken($tokens[$i], ')'))
- || ($this->_isToken($tokens[$i], 'T_WHITESPACE')))
- && $this->_isToken($tokens[$i+1], 'T_OBJECT_OPERATOR')) {
-
- $php5_method_chaining = true;
- }
- }
- }
-
- // Compare "ignore_functions_match" pre-condition
- if (is_string($ifm_compare)) {
…
Large files files are truncated, but you can click here to view the full file