????
Your IP : 18.191.166.195
<?php
/**
* Cli controller
*
* PHP Version 5.3.2
*
* Copyright (c) 2007-2010, Mayflower GmbH
* 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 Mayflower GmbH nor the names of his
* 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.
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @author Elger Thiele <elger.thiele@mayflower.de>
* @author Simon Kohlmeyer <simon.kohlmeyer@mayflower.de>
* @copyright 2007-2010 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version SVN: $Id$
* @link http://www.phpunit.de/
* @since File available since 0.1.0
*/
if (strpos('/opt/alt/php55//usr/share/pear', '@php_dir') === false) {
if (!defined('PHPCB_ROOT_DIR')) {
define('PHPCB_ROOT_DIR', '/opt/alt/php55//usr/share/pear/PHP_CodeBrowser');
}
if (!defined('PHPCB_TEMPLATE_DIR')) {
define('PHPCB_TEMPLATE_DIR', '/opt/alt/php55//usr/share/pear/data/PHP_CodeBrowser/templates');
}
} else {
if (!defined('PHPCB_ROOT_DIR')) {
define('PHPCB_ROOT_DIR', realpath(dirname(__FILE__) . '/../'));
}
if (!defined('PHPCB_TEMPLATE_DIR')) {
define('PHPCB_TEMPLATE_DIR', realpath(dirname(__FILE__) . '/../templates'));
}
}
require_once dirname(__FILE__) . '/Autoload.php';
require_once 'Console/CommandLine.php';
require_once 'File/Iterator/Autoload.php';
require_once 'Log.php';
/**
* CbCLIController
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @author Elger Thiele <elger.thiele@mayflower.de>
* @author Michel Hartmann <michel.hartmann@mayflower.de>
* @author Simon Kohlmeyer <simon.kohlmeyer@mayflower.de>
* @copyright 2007-2010 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version Release: 1.0.2
* @link http://www.phpunit.de/
* @since Class available since 0.1.0
*/
class CbCLIController
{
/**
* Path to the Cruise Control input xml file
*
* @var string
*/
private $_logDir;
/**
* Path to the code browser html output folder
*
* @var string
*/
private $_htmlOutputDir;
/**
* Path to the project source code files
*
* @var string
*/
private $_projectSource;
/**
* Array of PCREs. Matching files will not appear in the output.
*
* @var Array
*/
private $_excludeExpressions;
/**
* Array of glob patterns. Matching files will not appear in the output.
*
* @var Array
*/
private $_excludePatterns;
/**
* The error plugin classes
*
* @var array
*/
private $_registeredPlugins;
/**
* The IOHelper used for filesystem interaction.
*
* @var CbIOHelper
*/
private $_ioHelper;
/**
* Pear Log object where debug output should go to.
*
* @var Log
*/
private $_debugLog;
/**
* Plugin-specific options. Formatted like
* array(
* 'CbErrorCRAP' => array(
* 'threshold' => 2
* )
* )
*
* @var array
*/
private $_pluginOptions = array();
/**
* File extensions that we take as php files.
*
* @var array
*/
private $_phpSuffixes;
/**
* The constructor
*
* Standard setters are initialized
*
* @param string $logPath The (path-to) xml log files. Can be null.
* @param Array $projectSource The project sources. Can be null.
* @param string $htmlOutputDir The html output dir, where new files will
* be created
* @param Array $excludeExpressions
* A list of PCREs. Files matching will not
* appear in the output.
* @param Array $pluginOptions Array of Arrays with plugin-specific
* options
* @param Array $excludePatterns A list of glob patterns. Files matching
* will not appear in the output.
* @param CbIOHelper $ioHelper The CbIOHelper object to be used for
* filesystem interaction.
*/
public function __construct($logPath, Array $projectSource,
$htmlOutputDir, Array $excludeExpressions,
Array $excludePatterns, Array $pluginOptions,
$ioHelper, $debugLog,
Array $phpSuffixes)
{
$this->_logDir = $logPath;
$this->_projectSource = $projectSource;
$this->_htmlOutputDir = $htmlOutputDir;
$this->_excludeExpressions = $excludeExpressions;
$this->_excludePatterns = $excludePatterns;
foreach ($pluginOptions as $plugin => $options) {
$this->_pluginOptions["CbError$plugin"] = $options;
}
$this->_ioHelper = $ioHelper;
$this->_debugLog = $debugLog;
$this->_registeredPlugins = array();
$this->_phpSuffixes = $phpSuffixes;
}
/**
* Setter/adder method for the used plugin classes.
* For each plugin to use, add it to this array
*
* @param mixed $classNames Definition of plugin classes
*
* @return void
*/
public function addErrorPlugins($classNames)
{
foreach ((array) $classNames as $className) {
$this->_registeredPlugins[] = $className;
}
}
/**
* Main execute function for PHP_CodeBrowser.
*
* Following steps are resolved:
* 1. Clean-up output directory
* 2. Merge xml log files
* 3. Generate cbXML file via errorlist from plugins
* 4. Save the cbErrorList as XML file
* 5. Generate HTML output from cbXML
* 6. Copy ressources (css, js, images) from template directory to output
*
* @return void
*/
public function run()
{
// clear and create output directory
if (is_dir($this->_htmlOutputDir)) {
$this->_ioHelper->deleteDirectory($this->_htmlOutputDir);
} else if (is_file($this->_htmlOutputDir)) {
$this->_ioHelper->deleteFile($this->_htmlOutputDir);
}
$this->_ioHelper->createDirectory($this->_htmlOutputDir);
// init needed classes
$cbViewReview = new CbViewReview(
PHPCB_TEMPLATE_DIR,
$this->_htmlOutputDir,
$this->_ioHelper,
$this->_phpSuffixes
);
$sourceHandler = new CbSourceHandler($this->_debugLog);
if (isset($this->_logDir)) {
$cbIssueXml = new CbIssueXml();
// merge xml files
$cbIssueXml->addDirectory($this->_logDir);
// conversion of XML file cc to cb format
foreach ($this->_registeredPlugins as $className) {
if (array_key_exists($className, $this->_pluginOptions)) {
$plugin = new $className(
$cbIssueXml,
$this->_pluginOptions[$className]
);
} else {
$plugin = new $className($cbIssueXml);
}
$sourceHandler->addPlugin($plugin);
}
}
if (isset($this->_projectSource)) {
foreach ($this->_projectSource as $source) {
if (is_dir($source)) {
$factory = new File_Iterator_Factory;
$suffixes = array_merge(
$this->_phpSuffixes,
array('php','js','css', 'html')
);
$sourceHandler->addSourceFiles(
$factory->getFileIterator(
$source,
$suffixes
)
);
} else {
$sourceHandler->addSourceFile($source);
}
}
}
array_walk(
$this->_excludeExpressions,
array($sourceHandler, 'excludeMatchingPCRE')
);
array_walk(
$this->_excludePatterns,
array($sourceHandler, 'excludeMatchingPattern')
);
$files = $sourceHandler->getFiles();
if (!$files) {
$cbViewReview->copyNoErrorsIndex();
} else {
// Get the path prefix all files have in common
$commonPathPrefix = $sourceHandler->getCommonPathPrefix();
$error_reporting = ini_get('error_reporting');
// Disable E_Strict, Text_Highlighter might throw up
ini_set('error_reporting', $error_reporting & ~E_STRICT);
foreach ($files as $file) {
$cbViewReview->generate(
$file->getIssues(),
$file->name(),
$commonPathPrefix
);
}
ini_set('error_reporting', $error_reporting);
// Copy needed ressources (eg js libraries) to output directory
$cbViewReview->copyRessourceFolders();
$cbViewReview->generateIndex($files);
}
}
/**
* Main method called by script
*
* @return void
*/
public static function main()
{
$parser = self::createCommandLineParser();
try {
$opts = $parser->parse()->options;
} catch (Exception $e) {
$parser->displayError($e->getMessage());
}
$errors = self::errorsForOpts($opts);
if ($errors) {
foreach ($errors as $e) {
error_log("[Error] $e\n");
}
exit(1);
}
// Convert the --ignore arguments to patterns
if (null !== $opts['ignore']) {
$dirSep = preg_quote(DIRECTORY_SEPARATOR, '/');
foreach (explode(',', $opts['ignore']) as $ignore) {
$ig = realpath($ignore);
if (!$ig) {
error_log("[Warning] $ignore does not exists");
} else {
$ig = preg_quote($ig, '/');
$opts['excludePCRE'][] = "/^$ig($dirSep|$)/";
}
}
}
// init new CLIController
$controller = new CbCLIController(
$opts['log'],
$opts['source'] ? $opts['source'] : array(),
$opts['output'],
$opts['excludePCRE'] ? $opts['excludePCRE'] : array(),
$opts['excludePattern'] ? $opts['excludePattern'] : array(),
$opts['crapThreshold'] ? array('CRAP' => array(
'threshold' => $opts['crapThreshold'])
)
: array(),
new CbIOHelper(),
$opts['debugExcludes'] ? Log::factory('console', '', 'PHPCB')
: Log::factory('null'),
$opts['phpSuffixes'] ? explode(',', $opts['phpSuffixes'])
: array('php')
);
$plugins = self::getAvailablePlugins();
if ($opts['disablePlugin']) {
foreach ($opts['disablePlugin'] as $idx => $val) {
$opts['disablePlugin'][$idx] = strtolower($val);
}
foreach ($plugins as $pluginKey => $plugin) {
$name = substr($plugin, strlen('CbError'));
if (in_array(strtolower($name), $opts['disablePlugin'])) {
// Remove it from the plugins list
unset($plugins[$pluginKey]);
}
}
}
$controller->addErrorPlugins($plugins);
try {
$controller->run();
} catch (Exception $e) {
error_log(
<<<HERE
[Error] {$e->getMessage()}
{$e->getTraceAsString()}
HERE
);
}
}
/**
* Returns a list of available plugins.
*
* Currently hard-coded.
*
* @return array of string Classnames of error plugins
*/
public static function getAvailablePlugins()
{
return array(
'CbErrorCheckstyle',
'CbErrorPMD',
'CbErrorCPD',
'CbErrorPadawan',
'CbErrorCoverage',
'CbErrorCRAP'
);
}
/**
* Checks the given options array for errors.
*
* @param Array Options as returned by Console_CommandLine->parse()
*
* @return Array of String Errormessages.
*/
private static function errorsForOpts($opts)
{
$errors = array();
if (!isset($opts['log'])) {
if (!isset($opts['source'])) {
$errors[] = 'Missing log or source argument.';
}
} else if (!file_exists($opts['log'])) {
$errors[] = 'Log directory does not exist.';
} else if (!is_dir($opts['log'])) {
$errors[] = 'Log argument must be a directory, a file was given.';
}
if (!isset($opts['output'])) {
$errors[] = 'Missing output argument.';
} else if (file_exists($opts['output']) && !is_dir($opts['output'])) {
$errors[] = 'Ouput argument must be a directory, a file was given.';
}
if (isset($opts['source'])) {
foreach ($opts['source'] as $s) {
if (!file_exists($s)) {
$errors[] = "Source '$s' does not exist";
}
}
}
return $errors;
}
/**
* Creates a Console_CommandLine object to parse options.
*
* @return Console_CommandLine
*/
private static function createCommandLineParser()
{
$parser = new Console_CommandLine(
array(
'description' => 'A Code browser for PHP files with syntax '
. 'highlighting and colored error-sections '
. 'found by quality assurance tools like '
. 'PHPUnit or PHP_CodeSniffer.',
'version' => (strpos('1.0.2', '@') === false)
? '1.0.2'
: 'from Git'
)
);
$parser->addOption(
'log',
array(
'description' => 'The path to the xml log files, e.g. generated'
. ' from PHPUnit. Either this or --source '
. 'must be given',
'short_name' => '-l',
'long_name' => '--log',
'help_name' => '<directory>'
)
);
$parser->addOption(
'phpSuffixes',
array(
'description' => 'A comma separated list of php file extensions'
.' to include.',
'short_name' => '-S',
'long_name' => '--extensions',
'help_name' => '<extensions>'
)
);
$parser->addOption(
'output',
array(
'description' => 'Path to the output folder where generated '
. 'files should be stored.',
'short_name' => '-o',
'long_name' => '--output',
'help_name' => '<directory>'
)
);
$parser->addOption(
'source',
array(
'description' => 'Path to the project source code. Can either '
. 'be a directory or a single file. Parse '
. 'complete source directory if set, else '
. 'only files found in logs. Either this or'
. ' --log must be given. Can be given '
. 'multiple times',
'short_name' => '-s',
'long_name' => '--source',
'action' => 'StoreArray',
'help_name' => '<dir|file>'
)
);
$parser->addOption(
'ignore',
array(
'description' => 'Comma separated string of files or '
. 'directories that will be ignored during'
. 'the parsing process.',
'short_name' => '-i',
'long_name' => '--ignore',
'help_name' => '<files>'
)
);
$parser->addOption(
'excludePattern',
array(
'description' => 'Excludes all files matching the given glob '
. 'pattern. This is done after pulling the '
. 'files in the source dir in if one is '
. 'given. Can be given multiple times. Note'
. ' that the match is run against '
. 'absolute filenames.',
'short_name' => '-e',
'long_name' => '--exclude',
'action' => 'StoreArray',
'help_name' => '<pattern>'
)
);
$parser->addOption(
'excludePCRE',
array(
'description' => 'Works like -e but takes PCRE instead of '
. 'glob patterns.',
'short_name' => '-E',
'long_name' => '--excludePCRE',
'action' => 'StoreArray',
'help_name' => '<expression>'
)
);
$parser->addOption(
'debugExcludes',
array(
'description' => 'Print which files are excluded by which '
. 'expressions and patterns.',
'long_name' => '--debugExcludes',
'action' => 'StoreTrue'
)
);
$plugins = array_map(
array(__CLASS__, 'arrayMapCallback'),
self::getAvailablePlugins()
);
$parser->addOption(
'disablePlugin',
array(
'description' => 'Disable single Plugins. Can be one of '
. implode(', ', $plugins),
'choices' => $plugins,
'long_name' => '--disablePlugin',
'action' => 'StoreArray',
'help_name' => '<plugin>'
)
);
$parser->addOption(
'crapThreshold',
array(
'description' => 'The minimum value for CRAP errors to be '
. 'recognized. Defaults to 0. Regardless '
. 'of this setting, values below 30 will '
. 'be considered notices, those above '
. 'warnings.',
'long_name' => '--crapThreshold',
'action' => 'StoreInt',
'help_name' => '<threshold>'
)
);
return $parser;
}
private static function arrayMapCallback($class)
{
return '"' . substr($class, strlen('CbError')) . '"';
}
}