Viewing file: Parser.php (69.54 KB) -rw-rw-rw- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
<?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)) {
if (strcasecmp('preg_match', $ifm_compare) != 0) {
// Try to catch function_exists() condition
if ($this->_isToken($tokens[$i], 'T_STRING')
&& (strcasecmp($tokens[$i][1], $ifm_compare) == 0)) {
while ((!$this->_isToken($tokens[$i],
'T_CONSTANT_ENCAPSED_STRING'))) {
$i += 1;
}
$func = trim($tokens[$i][1], "'");
/**
* try if function_exists()
* match one or more pattern condition
*/
foreach ($ifm_patterns as $pattern) {
if (preg_match($pattern, $func) === 1) {
$ignore_functions[] = $func;
}
}
}
}
}
// Compare "ignore_extensions_match" pre-condition
if (is_string($iem_compare)) {
if (strcasecmp('preg_match', $iem_compare) != 0) {
// Try to catch extension_loaded() condition
if ($this->_isToken($tokens[$i], 'T_STRING')
&& (strcasecmp($tokens[$i][1], $iem_compare) == 0)) {
while ((!$this->_isToken($tokens[$i],
'T_CONSTANT_ENCAPSED_STRING'))) {
$i += 1;
}
$ext = trim($tokens[$i][1], "'");
/**
* try if extension_loaded()
* match one or more pattern condition
*/
foreach ($iem_patterns as $pattern) {
if (preg_match($pattern, $ext) === 1) {
$ignore_extensions[] = $ext;
}
}
}
}
}
// Compare "ignore_constants_match" pre-condition
if (is_string($icm_compare)) {
if (strcasecmp('preg_match', $icm_compare) != 0) {
// Try to catch defined() condition
if ($this->_isToken($tokens[$i], 'T_STRING')
&& (strcasecmp($tokens[$i][1], $icm_compare) == 0)) {
while ((!$this->_isToken($tokens[$i],
'T_CONSTANT_ENCAPSED_STRING'))) {
$i += 1;
}
$cst = trim($tokens[$i][1], "'");
/**
* try if defined()
* match one or more pattern condition
*/
foreach ($icm_patterns as $pattern) {
if (preg_match($pattern, $cst) === 1) {
$ignore_constants[] = $cst;
}
}
}
}
}
// try to detect class instantiation
if ($this->_isToken($tokens[$i], 'T_STRING')
&& (isset($tokens[$i-2]))
&& $this->_isToken($tokens[$i-2], 'T_NEW')) {
$is_class = true;
$classes[] = $tokens[$i][1];
} else {
$is_class = false;
}
if ($this->_isToken($tokens[$i], 'T_STRING')
&& $is_class == false
&& (isset($tokens[$i+1]))
&& $this->_isToken($tokens[$i+1], '(')) {
$is_function = false;
if (isset($tokens[$i-1])
&& !$this->_isToken($tokens[$i-1], 'T_DOUBLE_COLON')
&& !$this->_isToken($tokens[$i-1], 'T_OBJECT_OPERATOR')) {
if (isset($tokens[$i-2])
&& $this->_isToken($tokens[$i-2], 'T_FUNCTION')) {
// its a function declaration
} else {
$is_function = true;
}
}
if ($is_function == true || !is_array($tokens[$i-1])) {
$functions[] = strtolower($tokens[$i][1]);
}
}
// try to detect condition function_exists()
if ($this->_isToken($tokens[$i], 'T_STRING')
&& (strcasecmp($tokens[$i][1], 'function_exists') == 0)) {
$j = $i;
while ((!$this->_isToken($tokens[$j], ')'))) {
if ($this->_isToken($tokens[$j], 'T_CONSTANT_ENCAPSED_STRING')) {
$t_string = $tokens[$j][1];
$t_string = trim($t_string, "'");
$t_string = trim($t_string, '"');
$function_exists[] = $t_string;
}
$j++;
}
}
// try to detect condition extension_loaded()
if ($this->_isToken($tokens[$i], 'T_STRING')
&& (strcasecmp($tokens[$i][1], 'extension_loaded') == 0)) {
$j = $i;
while ((!$this->_isToken($tokens[$j], ')'))) {
if ($this->_isToken($tokens[$j], 'T_CONSTANT_ENCAPSED_STRING')) {
$t_string = $tokens[$j][1];
$t_string = trim($t_string, "'");
$t_string = trim($t_string, '"');
$extension_loaded[] = $t_string;
}
$j++;
}
}
// try to detect condition defined()
if ($this->_isToken($tokens[$i], 'T_STRING')
&& (strcasecmp($tokens[$i][1], 'defined') == 0)) {
$j = $i;
while ((!$this->_isToken($tokens[$j], ')'))) {
if ($this->_isToken($tokens[$j], 'T_CONSTANT_ENCAPSED_STRING')) {
$t_string = $tokens[$j][1];
$t_string = trim($t_string, "'");
$t_string = trim($t_string, '"');
$defined[] = $t_string;
}
$j++;
}
}
// try to detect beginning of a class
if ($this->_isToken($tokens[$i], 'T_CLASS')) {
$found_class = true;
}
if (is_array($tokens[$i])) {
if (!isset($akeys)) {
// build contents one time only (static variable)
$akeys = array_keys($GLOBALS['_PHP_COMPATINFO_CONST']);
}
$const = strtoupper($tokens[$i][1]);
$found = array_search($const, $akeys);
if ($found !== false) {
if ($this->_isToken($tokens[$i], 'T_ENCAPSED_AND_WHITESPACE')) {
// PHP 5 constant tokens found into a string
} else {
// Compare "ignore_constants_match" free condition
$icm_preg_match = false;
if (is_string($icm_compare)) {
if (strcasecmp('preg_match', $icm_compare) == 0) {
/**
* try if preg_match()
* match one or more pattern condition
*/
foreach ($icm_patterns as $pattern) {
if (preg_match($pattern, $const) === 1) {
$icm_preg_match = true;
break;
}
}
}
}
$init = $GLOBALS['_PHP_COMPATINFO_CONST'][$const]['init'];
if (!PHP_CompatInfo_Parser::_ignore($init,
$min_ver, $max_ver)) {
$constants[] = $const;
if (in_array($const, $ignore_constants)
|| in_array($const, $options['ignore_constants'])
|| $icm_preg_match) {
$ignored_constants[] = $const;
} else {
$latest_version = $init;
}
}
}
}
}
$i += 1;
}
$classes = array_unique($classes);
$functions = array_unique($functions);
if (isset($options['ignore_functions'])) {
$options['ignore_functions']
= array_map('strtolower', $options['ignore_functions']);
} else {
$options['ignore_functions'] = array();
}
if (count($ignore_functions) > 0) {
$ignore_functions = array_map('strtolower', $ignore_functions);
$options['ignore_functions']
= array_merge($options['ignore_functions'], $ignore_functions);
$options['ignore_functions']
= array_unique($options['ignore_functions']);
}
if (count($ignore_extensions) > 0) {
$options['ignore_extensions']
= array_merge($options['ignore_extensions'], $ignore_extensions);
$options['ignore_extensions']
= array_unique($options['ignore_extensions']);
}
foreach ($classes as $name) {
if (!isset($GLOBALS['_PHP_COMPATINFO_CLASS'][$name])) {
continue; // skip this unknown class
}
$class = $GLOBALS['_PHP_COMPATINFO_CLASS'][$name];
if (PHP_CompatInfo_Parser::_ignore($class['init'], $min_ver, $max_ver)) {
continue; // skip this class version
}
$cmp = version_compare($latest_version, $class['init']);
if ($cmp === -1) {
$latest_version = $class['init'];
}
if (array_key_exists('end', $class)) {
$cmp = version_compare($earliest_version, $class['end']);
if ($earliest_version == '' || $cmp === 1) {
$earliest_version = $class['end'];
}
}
if (array_key_exists('ext', $class)) {
// this class depends of an extension
$extensions[] = $class['ext'];
}
}
foreach ($functions as $name) {
if (!isset($GLOBALS['_PHP_COMPATINFO_FUNCS'][$name])) {
continue; // skip this unknown function
}
$func = $GLOBALS['_PHP_COMPATINFO_FUNCS'][$name];
// retrieve if available the extension name
if ((isset($func['ext']))
&& ($func['ext'] != 'standard')
&& ($func['ext'] != 'zend')) {
$extension = $func['ext'];
} else {
$extension = false;
}
// Compare "ignore_functions_match" free condition
$ifm_preg_match = false;
if (is_string($ifm_compare)) {
if (strcasecmp('preg_match', $ifm_compare) == 0) {
/**
* try if preg_match()
* match one or more pattern condition
*/
foreach ($ifm_patterns as $pattern) {
if (preg_match($pattern, $name) === 1) {
$ifm_preg_match = true;
break;
}
}
}
}
if ((!in_array($name, $udf))
&& (!in_array($name, $options['ignore_functions']))
&& ($ifm_preg_match === false)) {
if ($extension && !in_array($extension, $extensions)) {
$extensions[] = $extension;
}
// Compare "ignore_extensions_match" free condition
$iem_preg_match = false;
if (is_string($iem_compare)) {
if (strcasecmp('preg_match', $iem_compare) == 0) {
/**
* try if preg_match()
* match one or more pattern condition
*/
foreach ($iem_patterns as $pattern) {
if (preg_match($pattern, $extension) === 1) {
$iem_preg_match = true;
break;
}
}
}
}
if ($extension
&& (in_array($extension, $options['ignore_extensions'])
|| $iem_preg_match)) {
if (!in_array($extension, $ignored_extensions)) {
// extension is ignored (only once)
$ignored_extensions[] = $extension;
}
// all extension functions are also ignored
$ignored_functions[] = $name;
continue; // skip this extension function
}
if (PHP_CompatInfo_Parser::_ignore($func['init'],
$min_ver, $max_ver)) {
continue; // skip this function version
}
if ($options['debug'] == true) {
$functions_version[$func['init']][] = array(
'function' => $name,
'extension' => $extension,
'pecl' => $func['pecl']
);
}
if ($extension === false
|| (isset($func['pecl']) && $func['pecl'] === false) ) {
$cmp = version_compare($latest_version, $func['init']);
if ($cmp === -1) {
$latest_version = $func['init'];
}
if (array_key_exists('end', $func)) {
$cmp = version_compare($earliest_version, $func['end']);
if ($earliest_version == '' || $cmp === 1) {
$earliest_version = $func['end'];
}
}
}
} else {
// function is ignored
$ignored_functions[] = $name;
}
}
$ignored_constants = array_unique($ignored_constants);
$constants = array_unique($constants);
foreach ($constants as $constant) {
$const = $GLOBALS['_PHP_COMPATINFO_CONST'][$constant];
if (PHP_CompatInfo_Parser::_ignore($const['init'], $min_ver, $max_ver)) {
continue; // skip this constant version
}
if (!in_array($constant, $ignored_constants)) {
$cmp = version_compare($latest_version, $const['init']);
if ($cmp === -1) {
$latest_version = $const['init'];
}
if (array_key_exists('end', $const)) {
$cmp = version_compare($earliest_version, $const['end']);
if ($earliest_version == '' || $cmp === 1) {
$earliest_version = $const['end'];
}
}
}
if (!in_array($const['name'], $constant_names)) {
// split PHP5 tokens and pure PHP constants
if ($const['name'] == strtolower($const['name'])) {
$token_names[] = $const['name'];
} else {
$constant_names[] = $const['name'];
}
}
}
if (isset($php5_method_chaining)
&& $php5_method_chaining === true
&& version_compare($latest_version, '5.0.0') < 0) {
// when PHP Method chaining is detected, only available for PHP 5
$latest_version = '5.0.0';
}
ksort($functions_version);
if (count($function_exists) > 0) {
$function_exists = array_unique($function_exists);
$cond_code += 1;
}
if (count($extension_loaded) > 0) {
$extension_loaded = array_unique($extension_loaded);
$cond_code += 2;
}
if (count($defined) > 0) {
$defined = array_unique($defined);
$cond_code += 4;
}
$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($constant_names);
sort($token_names);
$main_info = array('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' => $constant_names,
'tokens' => $token_names,
'cond_code' => $cond_code);
$functions_version = array_merge($main_info, $functions_version);
return $functions_version;
}
/**
* Checks if function which has $init version should be keep
* or ignore (version is between $min_ver and $max_ver).
*
* @param string $init version of current function
* @param string $min_ver minimum version of function to ignore
* @param string $max_ver maximum version of function to ignore
*
* @access private
* @return boolean True to ignore function/constant, false otherwise
* @since version 1.4.0 (2006-09-27)
* @static
*/
function _ignore($init, $min_ver, $max_ver)
{
if ($min_ver) {
$cmp = version_compare($init, $min_ver);
if ($max_ver && $cmp >= 0) {
$cmp = version_compare($init, $max_ver);
if ($cmp < 1) {
return true;
}
} elseif ($cmp === 0) {
return true;
}
}
return false;
}
/**
* Checks if the given token is of this symbolic name
*
* @param mixed $token Single PHP token to test
* @param string $symbolic Symbolic name of the given token
*
* @access private
* @return bool
* @since version 1.7.0b4 (2008-04-03)
*/
function _isToken($token, $symbolic)
{
if (is_array($token)) {
$t = token_name($token[0]);
} else {
$t = $token;
}
return ($t == $symbolic);
}
/**
* Computes the difference of arrays
*
* Computes the difference of arrays and returns result without original keys
*
* @param array $array1 The array to compare from
* @param array $array2 The array to compare against
*
* @access private
* @static
* @link http://www.php.net/manual/en/function.array-diff.php#82297
* @return array
* @since version 1.8.0b2 (2008-06-03)
*/
function _arrayDiff($array1, $array2)
{
// This wrapper for array_diff rekeys the array returned
$valid_array = array_diff($array1, $array2);
// reinstantiate $array1 variable
$array1 = array();
// loop through the validated array and move elements to $array1
// this is necessary because the array_diff function
// returns arrays that retain their original keys
foreach ($valid_array as $valid) {
$array1[] = $valid;
}
return $array1;
}
}
?>
|