/** * Execute the PhpCompatibility plugin */ protected function _execute() { $options = array('recursive' => true, 'report' => 'summary'); $min = 0; $minReadable = 0; $max = INF; $maxReadable = 'latest'; try { $phpci = new \PHP_CompatInfo($options); $phpci->parse($this->_extensionPath); $allResultsAtOnce = $phpci->toArray(); foreach ($phpci->toArray() as $file => $result) { if ($file == 'versions') { $currentMin = $this->_getVersionInt($result[0]); $currentMax = $this->_getVersionInt($result[1]); if (false == is_null($currentMin) && $min < $currentMin) { $min = $currentMin; $minReadable = $result[0]; } if (false == is_null($currentMax) && $currentMax < $max) { $max = $currentMax; $maxReadable = $result[1]; } } } } catch (\PHP_CompatInfo_Exception $e) { die('PHP_CompatInfo Exception : ' . $e->getMessage() . PHP_EOL); } if ($min <= $this->_getVersionInt($this->_settings->min) && $maxReadable == 'latest') { IssueHandler::addIssue(new Issue(array("extension" => $this->_extensionPath, "checkname" => $this->_pluginName, "type" => 'php_compatibility', "comment" => vsprintf('Extension is compatible to PHP from version %s up to latest versions', array($minReadable)), "failed" => false))); return; } IssueHandler::addIssue(new Issue(array("extension" => $this->_extensionPath, "checkname" => $this->_pluginName, "type" => 'php_compatibility', "comment" => vsprintf('Extension is compatible to PHP from version %s (instead of required %s) up to %s', array($minReadable, $this->_settings->min, $maxReadable)), "failed" => true))); }
/** * Class constructor for full/combined report * * @param string $source Data source * @param array $options Options for parser * @param array $warnings List of warning messages already produced * @param array $reportChilds List of reports to print */ public function __construct($source, $options, $warnings, $reportChilds) { $pci = new PHP_CompatInfo($options); if ($pci->parse($source) === false) { return; } $reportResults = $pci->toArray(); $masterResults = $reportResults[0]; if ($options['verbose'] < 3) { $reportResults = $reportResults[0]; } else { unset($reportResults[0]); } $base = realpath($source); if (is_file($base)) { $base = dirname($base); } $allWarnings = array_unique(array_merge($warnings, $pci->getWarnings())); $options = $pci->getOptions(); if (empty($reportChilds)) { $reportChilds = array('summary', 'extension', 'interface', 'trait', 'class', 'function', 'constant', 'global', 'token', 'condition'); } foreach ($reportChilds as $report) { $classReport = 'PHP_CompatInfo_Report_' . ucfirst($report); new $classReport($source, $options, $allWarnings, $reportResults); } echo PHP_EOL; if (count($allWarnings) > 0 && $options['verbose'] > 0) { echo 'Warning messages : (' . count($allWarnings) . ')' . PHP_EOL; echo PHP_EOL; foreach ($allWarnings as $warn) { if (in_array($warn, $warnings)) { // other listeners need to be notifed about console warnings $pci->addWarning($warn); } echo ' ' . $warn . PHP_EOL; } echo PHP_EOL; } if (class_exists('PHP_Timer', true) === true) { echo PHP_Timer::resourceUsage() . PHP_EOL; echo PHP_EOL; } echo 'Required PHP ' . $masterResults['versions'][0] . ' (min)'; if (!empty($masterResults['versions'][1])) { echo ', ' . $masterResults['versions'][1] . ' (max)'; } echo PHP_EOL; }
/** * Class constructor of source tokens report * * @param string $source Data source * @param array $options Options for parser * @param array $warnings List of warning messages already produced */ public function __construct($source, $options, $warnings) { if (isset($options['exclude']['files'])) { $excludes = $options['exclude']['files']; } else { $excludes = array(); } if (isset($options['fileExtensions'])) { $excludes[-1] = '\\.(' . implode('|', $options['fileExtensions']) . ')$'; } $files = PHP_CompatInfo::getFilelist($source, $options['recursive'], $excludes); $report = array_fill_keys($files, $options['verbose']); $base = realpath(dirname($source)); if (isset($options['reportFile'])) { ob_start(); } $this->generate($report, $base, $options['verbose']); if (isset($options['reportFile'])) { $generatedReport = ob_get_clean(); file_put_contents($options['reportFile'], $generatedReport, $options['reportFileFlags']); } }
/** * 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 $debug Show Extra Output * @access private * @return array * @since 0.7.0 */ function _parseTokens($tokens, $options) { static $akeys; $functions = array(); $functions_version = array(); $latest_version = $this->latest_version; $earliest_version = $this->earliest_version; $extensions = array(); $constants = array(); $constant_names = array(); $udf = array(); 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; } $token_count = sizeof($tokens); $i = 0; while ($i < $token_count) { $found_func = true; if (is_array($tokens[$i]) && token_name($tokens[$i][0]) == 'T_FUNCTION') { $found_func = false; } while ($found_func == false) { $i += 1; if (is_array($tokens[$i]) && token_name($tokens[$i][0]) == 'T_STRING') { $found_func = true; $udf[] = $tokens[$i][1]; } } if (is_array($tokens[$i]) && token_name($tokens[$i][0]) == 'T_STRING') { if (isset($tokens[$i + 1]) && $tokens[$i + 1][0] == '(') { if (is_array($tokens[$i - 1]) && token_name($tokens[$i - 1][0]) != 'T_DOUBLE_COLON' && token_name($tokens[$i - 1][0]) != 'T_OBJECT_OPERATOR') { $functions[] = strtolower($tokens[$i][1]); } elseif (!is_array($tokens[$i - 1])) { $functions[] = strtolower($tokens[$i][1]); } } } 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 (is_string($tokens[$i - 1]) || token_name($tokens[$i - 1][0]) == 'T_ENCAPSED_AND_WHITESPACE') { // PHP 5 constant tokens found into a string } else { if (!in_array($const, $options['ignore_constants'])) { if (!PHP_CompatInfo::_ignore($GLOBALS['_PHP_COMPATINFO_CONST'][$const]['init'], $min_ver, $max_ver)) { $constants[] = $const; $latest_version = $GLOBALS['_PHP_COMPATINFO_CONST'][$const]['init']; } } } } } $i += 1; } $functions = array_unique($functions); if (isset($options['ignore_functions'])) { $options['ignore_functions'] = array_map('strtolower', $options['ignore_functions']); } else { $options['ignore_functions'] = array(); } foreach ($functions as $name) { if (!isset($GLOBALS['_PHP_COMPATINFO_FUNCS'][$name])) { continue; // skip this unknown function } // retrieve if available the extension name if (isset($GLOBALS['_PHP_COMPATINFO_FUNCS'][$name]['ext']) && $GLOBALS['_PHP_COMPATINFO_FUNCS'][$name]['ext'] != 'ext_standard' && $GLOBALS['_PHP_COMPATINFO_FUNCS'][$name]['ext'] != 'zend') { $extension = substr($GLOBALS['_PHP_COMPATINFO_FUNCS'][$name]['ext'], 4); if ($extension[0] == '_') { $extension = substr($extension, 1); } } else { $extension = false; } if (!in_array($name, $udf) && !in_array($name, $options['ignore_functions'])) { if ($extension && in_array($extension, $options['ignore_extensions'])) { continue; // skip this extension function } if (PHP_CompatInfo::_ignore($GLOBALS['_PHP_COMPATINFO_FUNCS'][$name]['init'], $min_ver, $max_ver)) { continue; // skip this function version } if ($options['debug'] == true) { $functions_version[$GLOBALS['_PHP_COMPATINFO_FUNCS'][$name]['init']][] = array('function' => $name, 'extension' => $GLOBALS['_PHP_COMPATINFO_FUNCS'][$name]['ext']); } $cmp = version_compare($latest_version, $GLOBALS['_PHP_COMPATINFO_FUNCS'][$name]['init']); if ($cmp === -1) { $latest_version = $GLOBALS['_PHP_COMPATINFO_FUNCS'][$name]['init']; } if (array_key_exists('end', $GLOBALS['_PHP_COMPATINFO_FUNCS'][$name])) { $cmp = version_compare($earliest_version, $GLOBALS['_PHP_COMPATINFO_FUNCS'][$name]['end']); if ($earliest_version == '' || $cmp === 1) { $earliest_version = $GLOBALS['_PHP_COMPATINFO_FUNCS'][$name]['end']; } } if ($extension && !in_array($extension, $extensions)) { $extensions[] = $extension; } } } $constants = array_unique($constants); foreach ($constants as $constant) { if (PHP_CompatInfo::_ignore($GLOBALS['_PHP_COMPATINFO_CONST'][$constant]['init'], $min_ver, $max_ver)) { continue; // skip this constant version } $cmp = version_compare($latest_version, $GLOBALS['_PHP_COMPATINFO_CONST'][$constant]['init']); if ($cmp === -1) { $latest_version = $GLOBALS['_PHP_COMPATINFO_CONST'][$constant]['init']; } if (array_key_exists('end', $GLOBALS['_PHP_COMPATINFO_CONST'][$constant])) { $cmp = version_compare($earliest_version, $GLOBALS['_PHP_COMPATINFO_CONST'][$constant]['end']); if ($earliest_version == '' || $cmp === 1) { $earliest_version = $GLOBALS['_PHP_COMPATINFO_CONST'][$name]['end']; } } if (!in_array($GLOBALS['_PHP_COMPATINFO_CONST'][$constant]['name'], $constant_names)) { $constant_names[] = $GLOBALS['_PHP_COMPATINFO_CONST'][$constant]['name']; } } ksort($functions_version); $functions_version['constants'] = $constant_names; $functions_version['extensions'] = $extensions; $functions_version['version'] = $latest_version; $functions_version['max_version'] = $earliest_version; $functions_version = array_reverse($functions_version); return $functions_version; }
/** * Parse the given file or directory and determine the * minimum PHP version needed to execute the code. */ function execute() { // We render in text mode. We configure 40/12/40 columns for // filename/extension/constant rendering. $driverOptions = array('silent' => false, 'progress' => 'bar', 'colwidth' => array('f' => 50, 'e' => 12, 'c' => 40)); $info = new PHP_CompatInfo('text', $driverOptions); $info->parseData($this->input_file); }
if (empty($row)) { return; } echo "<tr>"; $tag = $header ? "th" : "td"; // link to file? $file = $row[0]; if (!empty($file) and substr($file, 0, 3) != '<b>' and $file != 'File') { $row[0] = '<a href="' . $PHP_SELF . '?file=' . urlencode($file) . '">' . $file . '</a>'; } foreach ($row as $r) { echo "<{$tag}>", empty($r) ? ' ' : "{$r}", "</{$tag}>"; } echo "</tr>\n"; } $info = new PHP_CompatInfo(); $dir = str_replace(array('\\', '/'), '/', dirname(__FILE__)); $dir = preg_replace('/\\/' . basename(dirname(__FILE__)) . '$/', '', $dir); $debug = !empty($_GET['debug']); $detail = !empty($_GET['detail']); // echo $dir; $options = array('file_ext' => array('php'), 'ignore_files' => array(__FILE__), 'recurse_dir' => true, 'ignore_functions' => array(), 'debug' => $debug or $detail); // var_dump($options); set_time_limit(240); $cols = array('File', 'Version', 'Extensions', 'Constants'); if (empty($_GET['file'])) { $file = false; echo "<h1>All Files</h1>\n"; echo " Show Details: <a href=\"", $_SERVER["SCRIPT_NAME"], "?detail=1\">YES</a>"; echo " <a href=\"", $_SERVER["SCRIPT_NAME"], "\">NO</a> <br>\n"; $r = $info->parseFolder($dir, $options);
/** * Retrieve the 'deps' option passed to the constructor * * @return array|PEAR_Error * @access private * @since 0.1 */ function _getDependencies() { if ($this->_detectDependencies) { $this->_traverseFileArray($this->_struc, $ret); $compatinfo = new PHP_CompatInfo(); $info = $compatinfo->parseArray($ret); $ret = $this->addDependency('php', $info['version'], 'ge', 'php', false); if (is_a($ret, 'PEAR_Error')) { return $ret; } foreach ($info['extensions'] as $ext) { $this->addDependency($ext, '', 'has', 'ext', false); } } if (isset($this->_packageXml['release_deps']) && is_array($this->_packageXml['release_deps'])) { return $this->_packageXml['release_deps']; } else { return array(); } }
/** * Retrieve the 'deps' option passed to the constructor * * @access private * @return void|PEAR_Error * @since 1.6.0a1 */ function _getDependencies() { if ($this->_detectDependencies) { $this->_traverseFileArray($this->_struc, $ret); $compatinfo = new PHP_CompatInfo(); $info = $compatinfo->parseArray($ret, $this->_detectDependencies); $max_version = empty($info['max_version']) ? false : $info['max_version']; $ret = $this->setPhpDep($info['version'], $max_version); if (is_a($ret, 'PEAR_Error')) { return $ret; } foreach ($info['extensions'] as $ext) { $this->addExtensionDep('required', $ext); } } return; }
/** * Produce dependencies for extensions using PEAR PHP_CompatInfo package. */ function extdeps($files) { require_once 'PHP/CompatInfo.php'; $info = new PHP_CompatInfo('null'); $res = $info->parseData($files); // minimum php version we accept // "%define php_min_version 5.1.2" in spec to minimum version to be 5.1.2 $version = max(PHP_MIN_VERSION, $res['version']); if (version_compare($version, '5.0.0', 'ge')) { # force php-<name> only deps when php5 # XXX what about php-pecl-<name> virtual provides? $fmt = 'php-%s'; $epoch = 4; } else { $fmt = 'php(%s)'; $epoch = 3; } echo "php-common >= ", $epoch, ":", $version, "\n"; // process extensions foreach ($res['extensions'] as $ext) { // bz2 ext is in php-bzip2 package if ($ext == 'bz2') { $ext = 'bzip2'; } // libxml ext is in php-xml package if ($ext == 'libxml') { $ext = 'xml'; } // these need to be lowercased if (in_array($ext, array('SPL', 'PDO', 'SQLite', 'Reflection', 'SimpleXML'))) { $ext = strtolower($ext); } printf("{$fmt}\n", $ext); } }
BeehiveForum is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Beehive; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ======================================================================*/ require 'Bartlett/PHP/CompatInfo/Autoload.php'; require 'Bartlett/PHP/CompatInfo.php'; set_time_limit(0); header('Content-Type: text/plain'); echo "Please wait checking Minimum PHP Version...\n\n"; $pci = new PHP_CompatInfo(); $minimum_version = "0"; $versions_array = array(); $extensions_array = array(); $ignore_result_keys = array('ignored_files', 'ignored_functions', 'ignored_extensions', 'ignored_constants', 'max_version', 'version', 'classes', 'functions', 'extensions', 'constants', 'tokens', 'cond_code'); if (isset($_SERVER['argc']) && $_SERVER['argc'] > 1) { $pci->parse(array_splice($_SERVER['argv'], 1)); } else { $options = array('debug' => false, 'recurse_dir' => true, 'ignore_dirs' => array('forum/ckeditor', 'forum/include/htmlpurifier', 'forum/include/locale', 'forum/include/swift')); $pci->parse('forum'); } $results = $pci->toArray(); foreach ($results[0]['extensions'] as $extension_name => $extension_info) { if (in_array($extension_name, array('Core', 'standard'))) { continue; }
/** * Run the CLI version * * Run the CLI version of PHP_CompatInfo * * @return void * @access public * @since version 0.8.0 (2004-04-22) */ function run() { $args =& Console_Getargs::factory($this->opts); if (PEAR::isError($args)) { if ($args->getCode() === CONSOLE_GETARGS_HELP) { $error = ''; } else { $error = $args->getMessage(); } $this->_printUsage($error); return; } // default parser options $this->options = array('file_ext' => array('php', 'php4', 'inc', 'phtml'), 'recurse_dir' => true, 'debug' => false, 'is_string' => false, 'ignore_files' => array(), 'ignore_dirs' => array()); // version $V = $args->getValue('V'); if (isset($V)) { $error = 'PHP_CompatInfo (cli) version 1.8.1' . ' (http://pear.php.net/package/PHP_CompatInfo)'; echo $error; return; } // debug if ($args->isDefined('v')) { $v = $args->getValue('v'); if ($v > 3) { $this->options['debug'] = true; } } // no-recurse if ($args->isDefined('n')) { $this->options['recurse_dir'] = false; } // dir if ($args->isDefined('d')) { $d = $args->getValue('d'); if (file_exists($d)) { if ($d[strlen($d) - 1] == '/' || $d[strlen($d) - 1] == '\\') { $d = substr($d, 0, -1); } $this->dataSource = realpath($d); } else { $error = 'Failed opening directory "' . $d . '". Please check your spelling and try again.'; $this->_printUsage($error); return; } } // file if ($args->isDefined('f')) { $f = $args->getValue('f'); if (file_exists($f)) { $this->dataSource = $f; } else { $error = 'Failed opening file "' . $f . '". Please check your spelling and try again.'; $this->_printUsage($error); return; } } // string if ($args->isDefined('s')) { $s = $args->getValue('s'); if (!empty($s)) { $this->dataSource = sprintf("<?php %s ?>", $s); $this->options['is_string'] = true; } else { $error = 'Failed opening string "' . $s . '". Please check your spelling and try again.'; $this->_printUsage($error); return; } } // ignore-files $if = $args->getValue('if'); if (isset($if)) { if (file_exists($if)) { $options = $this->_parseParamFile($if); $this->options['ignore_files'] = $options['std']; } else { $error = 'Failed opening file "' . $if . '" (ignore-files option). ' . 'Please check your spelling and try again.'; $this->_printUsage($error); return; } } // ignore-dirs $id = $args->getValue('id'); if (isset($id)) { if (file_exists($id)) { $options = $this->_parseParamFile($id); $this->options['ignore_dirs'] = $options['std']; } else { $error = 'Failed opening file "' . $id . '" (ignore-dirs option). ' . 'Please check your spelling and try again.'; $this->_printUsage($error); return; } } // ignore-functions $in = $args->getValue('in'); if (isset($in)) { if (file_exists($in)) { $options = $this->_parseParamFile($in); $this->options['ignore_functions'] = $options['std']; } else { $error = 'Failed opening file "' . $in . '" (ignore-functions option). ' . 'Please check your spelling and try again.'; $this->_printUsage($error); return; } } // ignore-constants $ic = $args->getValue('ic'); if (isset($ic)) { if (file_exists($ic)) { $options = $this->_parseParamFile($ic); $this->options['ignore_constants'] = $options['std']; } else { $error = 'Failed opening file "' . $ic . '" (ignore-constants option). ' . 'Please check your spelling and try again.'; $this->_printUsage($error); return; } } // ignore-extensions $ie = $args->getValue('ie'); if (isset($ie)) { if (file_exists($ie)) { $options = $this->_parseParamFile($ie); $this->options['ignore_extensions'] = $options['std']; } else { $error = 'Failed opening file "' . $ie . '" (ignore-extensions option). ' . 'Please check your spelling and try again.'; $this->_printUsage($error); return; } } // ignore-versions $iv = $args->getValue('iv'); if (isset($iv)) { if (!is_array($iv)) { $iv = array($iv); } $this->options['ignore_versions'] = $iv; } // ignore-functions-match $inm = $args->getValue('inm'); if (isset($inm)) { if (file_exists($inm)) { $patterns = $this->_parseParamFile($inm, true); if (count($patterns['std']) > 0 && count($patterns['reg']) > 0) { $error = 'Mixed "function_exists" and ' . '"preg_match" conditions are not allowed. ' . 'Please check your spelling and try again.'; $this->_printUsage($error); return; } elseif (count($patterns['std']) > 0) { $this->options['ignore_functions_match'] = array('function_exists', $patterns['std']); } elseif (count($patterns['reg']) > 0) { $this->options['ignore_functions_match'] = array('preg_match', $patterns['reg']); } } else { $error = 'Failed opening file "' . $inm . '" (ignore-functions-match option). ' . 'Please check your spelling and try again.'; $this->_printUsage($error); return; } } // ignore-extensions-match $iem = $args->getValue('iem'); if (isset($iem)) { if (file_exists($iem)) { $patterns = $this->_parseParamFile($iem, true); if (count($patterns['std']) > 0 && count($patterns['reg']) > 0) { $error = 'Mixed "extension_loaded" and ' . '"preg_match" conditions are not allowed. ' . 'Please check your spelling and try again.'; $this->_printUsage($error); return; } elseif (count($patterns['std']) > 0) { $this->options['ignore_extensions_match'] = array('extension_loaded', $patterns['std']); } elseif (count($patterns['reg']) > 0) { $this->options['ignore_extensions_match'] = array('preg_match', $patterns['reg']); } } else { $error = 'Failed opening file "' . $iem . '" (ignore-extensions-match option). ' . 'Please check your spelling and try again.'; $this->_printUsage($error); return; } } // ignore-constants-match $icm = $args->getValue('icm'); if (isset($icm)) { if (file_exists($icm)) { $patterns = $this->_parseParamFile($icm, true); if (count($patterns['std']) > 0 && count($patterns['reg']) > 0) { $error = 'Mixed "defined" and ' . '"preg_match" conditions are not allowed. ' . 'Please check your spelling and try again.'; $this->_printUsage($error); return; } elseif (count($patterns['std']) > 0) { $this->options['ignore_constants_match'] = array('defined', $patterns['std']); } elseif (count($patterns['reg']) > 0) { $this->options['ignore_constants_match'] = array('preg_match', $patterns['reg']); } } else { $error = 'Failed opening file "' . $icm . '" (ignore-constants-match option). ' . 'Please check your spelling and try again.'; $this->_printUsage($error); return; } } // file-ext if ($args->isDefined('d') && $args->isDefined('fe')) { $fe = $args->getValue('fe'); if (is_string($fe)) { $this->options['file_ext'] = explode(',', $fe); } else { $error = 'No valid file extensions provided "' . '". Please check your spelling and try again.'; $this->_printUsage($error); return; } } // file or directory options are minimum required to work if (!$args->isDefined('f') && !$args->isDefined('d') && !$args->isDefined('s')) { $error = 'ERROR: You must supply at least ' . 'one string, file or directory to process'; $this->_printUsage($error); return; } if ($args->isDefined('r')) { $report = $args->getValue('r'); } else { $report = 'text'; } if ($args->isDefined('t')) { $defs = array('f' => 29, 'e' => 12, 'c' => 20); $tabs = $args->getValue('t'); $tabs = explode(',', $tabs); for ($t = 0; $t < 3; $t++) { if (isset($tabs[$t])) { if ($t == 0) { $defs['f'] = (int) $tabs[$t]; } elseif ($t == 1) { $defs['e'] = (int) $tabs[$t]; } else { $defs['c'] = (int) $tabs[$t]; } } } $conf = array('colwidth' => $defs); } else { $conf = array(); } $conf = array_merge($conf, array('args' => $args->getValues())); $compatInfo = new PHP_CompatInfo($report, $conf); // dir if ($args->isDefined('d')) { $d = $args->getValue('d'); $files = $compatInfo->parser->getFilelist($d, $this->options); if (count($files) == 0) { $error = 'No valid files into directory "' . $d . '". Please check your spelling and try again.'; $this->_printUsage($error); return; } } $compatInfo->parseData($this->dataSource, $this->options); }
/** * Magic methods to get informations on parsing results about * excludes, includes, extensions, * namespaces, interfaces, traits, classes, functions, constants, globals * * @param string $name Method name invoked * @param array $args Method arguments provided * * @return array * @throws PHP_CompatInfo_Exception */ public function __call($name, $args) { $pattern = '/get' . '(?>(Excludes|Includes' . '|Extensions' . '|Namespaces|Interfaces|Traits|Classes|Functions|Constants|Globals))/'; if (preg_match($pattern, $name, $matches) === 0) { throw new PHP_CompatInfo_Exception("Invalid method. Given '{$name}'", PHP_CompatInfo_Exception::RUNTIME); } $group = strtolower($matches[1]); if ('traits' === $group && version_compare(phpversion(), '5.4.0', 'lt')) { return; } $category = isset($args[0]) ? $args[0] : null; $pattern = isset($args[1]) ? $args[1] : null; self::$filterVersion = isset($args[2]) ? $args[2] : $this->options['filterVersion']; self::$filterOperator = isset($args[3]) ? $args[3] : $this->options['filterOperator']; if (isset($category) && !$this->isValid($category, $group)) { throw new PHP_CompatInfo_Exception("Invalid category. Given '{$category}'", PHP_CompatInfo_Exception::RUNTIME); } $results = array(); if (in_array($group, array('includes', 'excludes', 'extensions', 'namespaces', 'interfaces', 'traits', 'classes', 'functions', 'constants', 'globals'))) { $results = $this->results[0][$group]; } if (isset($pattern) && is_string($pattern)) { foreach ($results[$category] as $name => $values) { if (preg_match("/{$pattern}/", $name) === 0) { unset($results[$category][$name]); } } } if (in_array($group, array('extensions', 'namespaces', 'interfaces', 'traits', 'classes', 'functions', 'constants'))) { self::applyFilter($results, $category); } if (isset($category)) { if (isset($results[$category])) { $results = $results[$category]; } else { $results = array(); } } return $results; }
/** * Handle console input and produce the appropriate report requested * * @return void * @throws PHP_CompatInfo_Exception If report is not available. */ public static function main() { $input = new Console_CommandLine(array('name' => 'phpcompatinfo', 'description' => 'PHP_CompatInfo (cli) by Laurent Laville.', 'version' => self::getVersion())); // common options to all sub-commands $input->addOption('xmlFile', array('long_name' => '--configuration', 'action' => 'StoreString', 'description' => 'Read configuration from XML file')); $input->addOption('noConfiguration', array('long_name' => '--no-configuration', 'action' => 'StoreTrue', 'description' => 'Ignore default configuration file ' . '(phpcompatinfo.xml)')); $input->addOption('iniSet', array('short_name' => '-d', 'long_name' => '--ini-set', 'action' => 'StoreArray', 'description' => 'Sets a php.ini directive value')); $input->addOption('verbose', array('short_name' => '-v', 'long_name' => '--verbose', 'action' => 'Counter', 'description' => 'Output more verbose information')); // options relatives and common to sub-commands $referenceOption = new Console_CommandLine_Option('reference', array('long_name' => '--reference', 'action' => 'StoreString', 'description' => 'The name of the reference to use', 'choices' => array('PHP5', 'ALL', 'DYN'))); $reportOption = new Console_CommandLine_Option('report', array('long_name' => '--report', 'action' => 'StoreArray', 'description' => 'Type of report', 'choices' => array('full', 'summary', 'source', 'xml', 'token', 'extension', 'namespace', 'trait', 'interface', 'class', 'function', 'constant', 'global', 'condition'))); $helpReferenceOption = new Console_CommandLine_Option('helpReference', array('long_name' => '--help-reference', 'action' => 'List', 'description' => 'List of reference available', 'action_params' => array('list' => array('PHP5', 'ALL', 'DYN')))); $helpReportOption = new Console_CommandLine_Option('helpReport', array('long_name' => '--help-report', 'action' => 'List', 'description' => 'List of report available', 'action_params' => array('list' => array('full', 'summary', 'source', 'xml', 'token', 'extension', 'namespace', 'trait', 'interface', 'class', 'function', 'constant', 'global', 'condition')))); $reportFileOption = new Console_CommandLine_Option('reportFile', array('long_name' => '--report-file', 'action' => 'StoreString', 'description' => 'Write the report to the specified file path')); $excludeIDOption = new Console_CommandLine_Option('excludeID', array('long_name' => '--exclude-pattern', 'action' => 'StoreString', 'description' => 'Exclude components' . ' from list referenced by ID provided')); $recursiveOption = new Console_CommandLine_Option('recursive', array('short_name' => '-R', 'long_name' => '--recursive', 'action' => 'StoreTrue', 'description' => 'Includes the contents of subdirectories')); $fileExtensionsOption = new Console_CommandLine_Option('fileExtensions', array('long_name' => '--file-extensions', 'action' => 'StoreString', 'description' => 'A comma separated list of file extensions to check')); // options relatives to print sub-command $filterVersionOption = new Console_CommandLine_Option('filterVersion', array('long_name' => '--filter-version', 'action' => 'StoreString', 'description' => 'The version to compare with each element found')); $filterOperatorOption = new Console_CommandLine_Option('filterOperator', array('long_name' => '--filter-operator', 'action' => 'StoreString', 'description' => 'The version test relationship', 'choices' => array('lt', 'le', 'gt', 'ge', 'eq', 'ne'))); // argument common to all list sub-commands except to list and list-references $referenceArgument = new Console_CommandLine_Argument('reference', array('description' => '(optional) Limit output only to this reference', 'optional' => true)); // clear-cache sub-command $clearcacheCmd = $input->addCommand('clear-cache', array('description' => 'Clear Parser Cache')); $clearcacheCmd->addArgument('sourceFile', array('description' => 'The source file in cache entries to delete.', 'optional' => true)); // print sub-command $printCmd = $input->addCommand('print', array('description' => 'Print a report of data source parsed.')); $printCmd->addOption($referenceOption); $printCmd->addOption($reportOption); $printCmd->addOption($reportFileOption); $printCmd->addOption($excludeIDOption); $printCmd->addOption($recursiveOption); $printCmd->addOption($fileExtensionsOption); $printCmd->addOption($filterVersionOption); $printCmd->addOption($filterOperatorOption); $printCmd->addOption($helpReferenceOption); $printCmd->addOption($helpReportOption); $printCmd->addArgument('sourcePath', array('description' => 'The data source to scan (file or directory).')); // list-references sub-command $listReferencesCmd = $input->addCommand('list-references', array('description' => 'List all extensions supported.')); $listReferencesCmd->addOption($filterVersionOption); $listReferencesCmd->addOption($filterOperatorOption); $listReferencesCmd->addOption($reportFileOption); $listReferencesCmd->addArgument($referenceArgument); // list sub-command $listCmd = $input->addCommand('list', array('description' => 'List all "elements" referenced in the data base.')); $listCmd->addOption($referenceOption); $listCmd->addOption($filterVersionOption); $listCmd->addOption($filterOperatorOption); $listCmd->addOption($reportFileOption); $listCmd->addOption($helpReferenceOption); $listCmd->addArgument('element', array('description' => 'May be either ' . '"extensions", ' . '"interfaces", "classes", ' . '"functions" or "constants"', 'choices' => array('extensions', 'interfaces', 'classes', 'functions', 'constants'), 'multiple' => true)); // list-extensions sub-command $listExtensionsCmd = $input->addCommand('list-extensions', array('description' => 'List all extensions referenced in the data base.')); $listExtensionsCmd->addOption($referenceOption); $listExtensionsCmd->addOption($filterVersionOption); $listExtensionsCmd->addOption($filterOperatorOption); $listExtensionsCmd->addOption($reportFileOption); $listExtensionsCmd->addOption($helpReferenceOption); $listExtensionsCmd->addArgument($referenceArgument); // list-interfaces sub-command $listInterfacesCmd = $input->addCommand('list-interfaces', array('description' => 'List all interfaces referenced in the data base.')); $listInterfacesCmd->addOption($referenceOption); $listInterfacesCmd->addOption($filterVersionOption); $listInterfacesCmd->addOption($filterOperatorOption); $listInterfacesCmd->addOption($reportFileOption); $listInterfacesCmd->addOption($helpReferenceOption); $listInterfacesCmd->addArgument($referenceArgument); // list-classes sub-command $listClassesCmd = $input->addCommand('list-classes', array('description' => 'List all classes referenced in the data base.')); $listClassesCmd->addOption($referenceOption); $listClassesCmd->addOption($filterVersionOption); $listClassesCmd->addOption($filterOperatorOption); $listClassesCmd->addOption($reportFileOption); $listClassesCmd->addOption($helpReferenceOption); $listClassesCmd->addArgument($referenceArgument); // list-functions sub-command $listFunctionsCmd = $input->addCommand('list-functions', array('description' => 'List all functions referenced in the data base.')); $listFunctionsCmd->addOption($referenceOption); $listFunctionsCmd->addOption($filterVersionOption); $listFunctionsCmd->addOption($filterOperatorOption); $listFunctionsCmd->addOption($reportFileOption); $listFunctionsCmd->addOption($helpReferenceOption); $listFunctionsCmd->addArgument($referenceArgument); // list-constants sub-command $listConstantsCmd = $input->addCommand('list-constants', array('description' => 'List all constants referenced in the data base.')); $listConstantsCmd->addOption($referenceOption); $listConstantsCmd->addOption($filterVersionOption); $listConstantsCmd->addOption($filterOperatorOption); $listConstantsCmd->addOption($reportFileOption); $listConstantsCmd->addOption($helpReferenceOption); $listConstantsCmd->addArgument($referenceArgument); try { $result = $input->parse(); $command = $result->command_name; if (empty($command)) { $input->displayUsage(1); } } catch (Exception $e) { $input->displayError($e->getMessage()); } $warnings = array(); // Loads the default or custom configuration (if available) $options = array('reference' => '', 'verbose' => false, 'listeners' => array()); $reports = array(); $consoleProgress = true; $reportFileAppend = false; if ($result->options['noConfiguration'] !== true) { if (!isset($result->options['xmlFile'])) { // use default configuration $dir = '@cfg_dir@' . DIRECTORY_SEPARATOR . 'PHP_CompatInfo'; if (strpos($dir, '@') === false) { // PEAR installer was used to install the package } else { // manual install $dir = getcwd(); } $filename = $dir . DIRECTORY_SEPARATOR . 'phpcompatinfo.xml'; if (file_exists($filename)) { $config = $filename; } elseif (file_exists($filename . '.dist')) { $config = $filename . '.dist'; } else { $config = false; } } else { $filename = $result->options['xmlFile']; if (file_exists($filename)) { $config = realpath($filename); } else { $config = false; } } if ($config && is_file($config)) { // try to load the configuration file contents $configuration = PHP_CompatInfo_Configuration::getInstance($config); // check if components should be excluded if (isset($result->command->options['excludeID'])) { $patternID = $result->command->options['excludeID']; $excludes = $configuration->getExcludeConfiguration($patternID); if (count($excludes) == 0) { $warnings[] = "Exclude pattern ID '{$patternID}'" . " does not exist, or is empty"; } else { $haystack = array('extension', 'interface', 'trait', 'function', 'constant'); foreach ($excludes as $key => $values) { if (in_array($key, $haystack)) { $options['exclude'][$key . 's'] = $values; } elseif ('class' == $key) { $options['exclude']['classes'] = $values; } else { foreach ($values as $value) { $options['exclude']['files'][] = $value; } } } } } // set main options $phpcompatinfo = $configuration->getMainConfiguration(); if (isset($phpcompatinfo['reference'])) { $options['reference'] = $phpcompatinfo['reference']; } if (isset($phpcompatinfo['report'])) { $reports = $phpcompatinfo['report']; } if (isset($phpcompatinfo['reportFile'])) { $reportFile = $phpcompatinfo['reportFile']; } if (isset($phpcompatinfo['reportFileAppend'])) { $reportFileAppend = $phpcompatinfo['reportFileAppend']; } if (isset($phpcompatinfo['cacheDriver'])) { $options['cacheDriver'] = $phpcompatinfo['cacheDriver']; } else { $options['cacheDriver'] = 'null'; } if (isset($phpcompatinfo['consoleProgress'])) { $consoleProgress = $phpcompatinfo['consoleProgress']; } if (isset($phpcompatinfo['verbose'])) { $options['verbose'] = $phpcompatinfo['verbose']; } if (isset($phpcompatinfo['recursive'])) { $options['recursive'] = $phpcompatinfo['recursive']; } if (isset($phpcompatinfo['fileExtensions'])) { $options['fileExtensions'] = $phpcompatinfo['fileExtensions']; } // sets cache options $options['cacheOptions'] = $configuration->getCacheConfiguration($options['cacheDriver']); // sets extension references limit $extensions = $configuration->getReferenceConfiguration(); if (count($extensions) > 0) { $options['extensions'] = $extensions; } // sets php.ini directives $ini = $configuration->getPHPConfiguration(); foreach ($ini as $name => $value) { ini_set($name, $value); } // sets listeners instances $listeners = $configuration->getListenerConfiguration(); foreach ($listeners as $listener) { if (!class_exists($listener['class'], false) && $listener['file'] !== '') { include_once $listener['file']; } if (class_exists($listener['class'], true)) { if (count($listener['arguments']) == 0) { $listener = new $listener['class'](); } else { $listenerClass = new ReflectionClass($listener['class']); $listener = $listenerClass->newInstanceArgs($listener['arguments']); } if ($listener instanceof PHP_CompatInfo_Listener_Console && $consoleProgress === false) { /* Do not add the console listener if consoleProgress directive is off */ } else { if ($listener instanceof SplObserver) { $options['listeners'][] = $listener; } } } } // sets plugins system $plugins = $configuration->getPluginConfiguration(); foreach ($plugins as $plugin) { if (!class_exists($plugin['class'], false) && $plugin['file'] !== '') { include_once $plugin['file']; } if (class_exists($plugin['class'], true)) { $pluginClass = new ReflectionClass($plugin['class']); $reference = $pluginClass->newInstanceArgs($plugin['args']); if (!$reference instanceof PHP_CompatInfo_Reference_PluginsAbstract) { $warnings[] = "Plugin '" . $plugin['class'] . "' is not valid"; } unset($reference); } } if (count($plugins) > 0) { $options['referencePlugins'] = $plugins; } } elseif (isset($result->options['verbose'])) { $warnings[] = 'File "' . $filename . '" does not exist'; } } if ($consoleProgress === true) { $options['listeners'][] = new PHP_CompatInfo_Listener_Console(); } if (isset($result->command->options['reference'])) { $options['reference'] = $result->command->options['reference']; } if (empty($options['reference']) && !in_array($command, array('list-references', 'clear-cache'))) { $input->displayError('You must supply at least a reference'); } if (isset($result->options['iniSet'])) { foreach ($result->options['iniSet'] as $iniSet) { $ini = explode('=', $iniSet); if (isset($ini[0])) { if (isset($ini[1])) { ini_set($ini[0], $ini[1]); } else { ini_set($ini[0], true); } } } } if (isset($result->command->options['report'])) { $reports = $result->command->options['report']; } if (empty($reports)) { // default report $reports = array('summary'); } if (in_array('full', $reports)) { // when 'full' alias report is specified, ignored all others $reports = array(); $reportFileAppend = true; $fullReport = true; } $reportChilds = $reports; if (isset($result->command->options['reportFile'])) { $reportFile = $result->command->options['reportFile']; } if (isset($reportFile)) { if (is_dir($reportFile) || !file_exists(dirname($reportFile))) { $warnings[] = 'Report file: "' . $reportFile . '" is invalid'; } else { $options['reportFile'] = $reportFile; if ($reportFileAppend === true) { $options['reportFileFlags'] = FILE_APPEND; } else { $options['reportFileFlags'] = 0; } } } if (isset($result->command->options['filterVersion'])) { $options['filterVersion'] = $result->command->options['filterVersion']; } if (isset($result->command->options['filterOperator'])) { $options['filterOperator'] = $result->command->options['filterOperator']; } if ('print' == $command) { if (count($reports) == 0 && !isset($fullReport)) { $input->displayError('You must supply at least a type of report'); } $source = $result->command->args['sourcePath']; $report = 'full'; } elseif ('list' == $command) { $elements = $result->command->args['element']; $source = array_shift($elements); $report = 'reference'; $options['filterReference'] = null; } elseif ('list' == substr($command, 0, 4)) { list(, $source) = explode('-', $command); if ($source == 'references') { $report = 'database'; } else { $report = 'reference'; $elements = array(); } $options['filterReference'] = $result->command->args['reference']; } if (isset($result->command->options['recursive'])) { $options['recursive'] = $result->command->options['recursive']; } if (isset($result->command->options['fileExtensions'])) { $fileExtensions = explode(',', $result->command->options['fileExtensions']); $options['fileExtensions'] = array_map('trim', $fileExtensions); } if (isset($result->options['verbose'])) { $options['verbose'] = $result->options['verbose']; } if ('clear-cache' == $command) { $defaultOptions = PHP_CompatInfo::getDefaultOptions(); $driver = isset($options['cacheDriver']) ? $options['cacheDriver'] : $defaultOptions['cacheDriver']; $source = $result->command->args['sourceFile']; $cache = PHP_CompatInfo_Cache::getInstance($driver, $defaultOptions); $count = $cache->deleteCache($source); printf('%d cache entries cleared%s', $count, PHP_EOL); } else { try { self::factory($report, $source, $options, $warnings, $reportChilds); if ($report == 'reference') { $options['reportFileFlags'] = FILE_APPEND; while (count($elements) > 0) { $source = array_shift($elements); self::factory($report, $source, $options, $warnings, null); } } } catch (PHP_CompatInfo_Exception $e) { print $e->getMessage() . PHP_EOL; exit(1); } } }