From 4233886480aaa43e2b9eb1675b7203ec5b542354 Mon Sep 17 00:00:00 2001 From: jrfnl Date: Wed, 21 Mar 2018 03:13:45 +0100 Subject: [PATCH] Allow requesting a custom report using the report name or FQN MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows for external standards to provide portable custom reports while installed in an arbitrary directory. * The external standard has to make sure it includes an `` directive in the ruleset and sort out the loading of the custom report classes through a `spl_autoload_register()`-ed autoloader. * The name of the custom report class can be provided either on the command line using `--report=...` or via the ruleset using ``. * The name of the custom report class can be either the Fully Qualified report class name òr just the class name. - The FQN does not have to be prefixed with an `\`, but things will work just fine if it is. - If just the class name is provided, PHPCS will try to find the report in any of the namespaces as registered by the installed standards. - If the report class is not found in any of these, a `DeepExitException` will be thrown. Fixes 1942 --- autoload.php | 12 ++++++++++++ src/Reporter.php | 27 ++++++++++++++++++++++++++- 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/autoload.php b/autoload.php index e4d21ace08..108c80c13d 100644 --- a/autoload.php +++ b/autoload.php @@ -217,6 +217,18 @@ public static function addSearchPath($path, $nsPrefix='') }//end addSearchPath() + /** + * Retrieve the namespaces and paths registered by external standards. + * + * @return array + */ + public static function getSearchPaths() + { + return self::$searchPaths; + + }//end getSearchPaths() + + /** * Gets the class name for the given file path. * diff --git a/src/Reporter.php b/src/Reporter.php index b9a64c2617..62cb727389 100644 --- a/src/Reporter.php +++ b/src/Reporter.php @@ -105,6 +105,7 @@ public function __construct(Config $config) $output = $config->reportFile; } + $reportClassName = ''; if (strpos($type, '.') !== false) { // This is a path to a custom report class. $filename = realpath($type); @@ -114,8 +115,32 @@ public function __construct(Config $config) } $reportClassName = Autoload::loadFile($filename); - } else { + } else if (class_exists('PHP_CodeSniffer\Reports\\'.$type) === true) { + // PHPCS native report. $reportClassName = 'PHP_CodeSniffer\Reports\\'.$type; + } else if (class_exists($type) === true) { + // FQN of a custom report. + $reportClassName = $type; + } else { + // OK, so not a FQN, try and find the report using the registered namespaces. + $registeredNamespaces = Autoload::getSearchPaths(); + $trimmedType = ltrim($type, '\\'); + + foreach ($registeredNamespaces as $nsPrefix) { + if ($nsPrefix === '') { + continue; + } + + if (class_exists($nsPrefix.'\\'.$trimmedType) === true) { + $reportClassName = $nsPrefix.'\\'.$trimmedType; + break; + } + } + }//end if + + if ($reportClassName === '') { + $error = "ERROR: Class file for report \"$type\" not found".PHP_EOL; + throw new DeepExitException($error, 3); } $reportClass = new $reportClassName();