340 lines
11 KiB
PHP
340 lines
11 KiB
PHP
<?php
|
|
/**
|
|
* Functions for helping process standards.
|
|
*
|
|
* @author Greg Sherwood <gsherwood@squiz.net>
|
|
* @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600)
|
|
* @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
|
|
*/
|
|
|
|
namespace PHP_CodeSniffer\Util;
|
|
|
|
use PHP_CodeSniffer\Config;
|
|
|
|
class Standards
|
|
{
|
|
|
|
|
|
/**
|
|
* Get a list of paths where standards are installed.
|
|
*
|
|
* Unresolvable relative paths will be excluded from the results.
|
|
*
|
|
* @return array
|
|
*/
|
|
public static function getInstalledStandardPaths()
|
|
{
|
|
$ds = DIRECTORY_SEPARATOR;
|
|
|
|
$installedPaths = [dirname(dirname(__DIR__)).$ds.'src'.$ds.'Standards'];
|
|
$configPaths = Config::getConfigData('installed_paths');
|
|
if ($configPaths !== null) {
|
|
$installedPaths = array_merge($installedPaths, explode(',', $configPaths));
|
|
}
|
|
|
|
$resolvedInstalledPaths = [];
|
|
foreach ($installedPaths as $installedPath) {
|
|
if (substr($installedPath, 0, 1) === '.') {
|
|
$installedPath = Common::realPath(__DIR__.$ds.'..'.$ds.'..'.$ds.$installedPath);
|
|
if ($installedPath === false) {
|
|
continue;
|
|
}
|
|
}
|
|
|
|
$resolvedInstalledPaths[] = $installedPath;
|
|
}
|
|
|
|
return $resolvedInstalledPaths;
|
|
|
|
}//end getInstalledStandardPaths()
|
|
|
|
|
|
/**
|
|
* Get the details of all coding standards installed.
|
|
*
|
|
* Coding standards are directories located in the
|
|
* CodeSniffer/Standards directory. Valid coding standards
|
|
* include a Sniffs subdirectory.
|
|
*
|
|
* The details returned for each standard are:
|
|
* - path: the path to the coding standard's main directory
|
|
* - name: the name of the coding standard, as sourced from the ruleset.xml file
|
|
* - namespace: the namespace used by the coding standard, as sourced from the ruleset.xml file
|
|
*
|
|
* If you only need the paths to the installed standards,
|
|
* use getInstalledStandardPaths() instead as it performs less work to
|
|
* retrieve coding standard names.
|
|
*
|
|
* @param boolean $includeGeneric If true, the special "Generic"
|
|
* coding standard will be included
|
|
* if installed.
|
|
* @param string $standardsDir A specific directory to look for standards
|
|
* in. If not specified, PHP_CodeSniffer will
|
|
* look in its default locations.
|
|
*
|
|
* @return array
|
|
* @see getInstalledStandardPaths()
|
|
*/
|
|
public static function getInstalledStandardDetails(
|
|
$includeGeneric=false,
|
|
$standardsDir=''
|
|
) {
|
|
$rulesets = [];
|
|
|
|
if ($standardsDir === '') {
|
|
$installedPaths = self::getInstalledStandardPaths();
|
|
} else {
|
|
$installedPaths = [$standardsDir];
|
|
}
|
|
|
|
foreach ($installedPaths as $standardsDir) {
|
|
// Check if the installed dir is actually a standard itself.
|
|
$csFile = $standardsDir.'/ruleset.xml';
|
|
if (is_file($csFile) === true) {
|
|
$rulesets[] = $csFile;
|
|
continue;
|
|
}
|
|
|
|
if (is_dir($standardsDir) === false) {
|
|
continue;
|
|
}
|
|
|
|
$di = new \DirectoryIterator($standardsDir);
|
|
foreach ($di as $file) {
|
|
if ($file->isDir() === true && $file->isDot() === false) {
|
|
$filename = $file->getFilename();
|
|
|
|
// Ignore the special "Generic" standard.
|
|
if ($includeGeneric === false && $filename === 'Generic') {
|
|
continue;
|
|
}
|
|
|
|
// Valid coding standard dirs include a ruleset.
|
|
$csFile = $file->getPathname().'/ruleset.xml';
|
|
if (is_file($csFile) === true) {
|
|
$rulesets[] = $csFile;
|
|
}
|
|
}
|
|
}
|
|
}//end foreach
|
|
|
|
$installedStandards = [];
|
|
|
|
foreach ($rulesets as $rulesetPath) {
|
|
$ruleset = @simplexml_load_string(file_get_contents($rulesetPath));
|
|
if ($ruleset === false) {
|
|
continue;
|
|
}
|
|
|
|
$standardName = (string) $ruleset['name'];
|
|
$dirname = basename(dirname($rulesetPath));
|
|
|
|
if (isset($ruleset['namespace']) === true) {
|
|
$namespace = (string) $ruleset['namespace'];
|
|
} else {
|
|
$namespace = $dirname;
|
|
}
|
|
|
|
$installedStandards[$dirname] = [
|
|
'path' => dirname($rulesetPath),
|
|
'name' => $standardName,
|
|
'namespace' => $namespace,
|
|
];
|
|
}//end foreach
|
|
|
|
return $installedStandards;
|
|
|
|
}//end getInstalledStandardDetails()
|
|
|
|
|
|
/**
|
|
* Get a list of all coding standards installed.
|
|
*
|
|
* Coding standards are directories located in the
|
|
* CodeSniffer/Standards directory. Valid coding standards
|
|
* include a Sniffs subdirectory.
|
|
*
|
|
* @param boolean $includeGeneric If true, the special "Generic"
|
|
* coding standard will be included
|
|
* if installed.
|
|
* @param string $standardsDir A specific directory to look for standards
|
|
* in. If not specified, PHP_CodeSniffer will
|
|
* look in its default locations.
|
|
*
|
|
* @return array
|
|
* @see isInstalledStandard()
|
|
*/
|
|
public static function getInstalledStandards(
|
|
$includeGeneric=false,
|
|
$standardsDir=''
|
|
) {
|
|
$installedStandards = [];
|
|
|
|
if ($standardsDir === '') {
|
|
$installedPaths = self::getInstalledStandardPaths();
|
|
} else {
|
|
$installedPaths = [$standardsDir];
|
|
}
|
|
|
|
foreach ($installedPaths as $standardsDir) {
|
|
// Check if the installed dir is actually a standard itself.
|
|
$csFile = $standardsDir.'/ruleset.xml';
|
|
if (is_file($csFile) === true) {
|
|
$basename = basename($standardsDir);
|
|
$installedStandards[$basename] = $basename;
|
|
continue;
|
|
}
|
|
|
|
if (is_dir($standardsDir) === false) {
|
|
// Doesn't exist.
|
|
continue;
|
|
}
|
|
|
|
$di = new \DirectoryIterator($standardsDir);
|
|
$standardsInDir = [];
|
|
foreach ($di as $file) {
|
|
if ($file->isDir() === true && $file->isDot() === false) {
|
|
$filename = $file->getFilename();
|
|
|
|
// Ignore the special "Generic" standard.
|
|
if ($includeGeneric === false && $filename === 'Generic') {
|
|
continue;
|
|
}
|
|
|
|
// Valid coding standard dirs include a ruleset.
|
|
$csFile = $file->getPathname().'/ruleset.xml';
|
|
if (is_file($csFile) === true) {
|
|
$standardsInDir[$filename] = $filename;
|
|
}
|
|
}
|
|
}
|
|
|
|
natsort($standardsInDir);
|
|
$installedStandards += $standardsInDir;
|
|
}//end foreach
|
|
|
|
return $installedStandards;
|
|
|
|
}//end getInstalledStandards()
|
|
|
|
|
|
/**
|
|
* Determine if a standard is installed.
|
|
*
|
|
* Coding standards are directories located in the
|
|
* CodeSniffer/Standards directory. Valid coding standards
|
|
* include a ruleset.xml file.
|
|
*
|
|
* @param string $standard The name of the coding standard.
|
|
*
|
|
* @return boolean
|
|
* @see getInstalledStandards()
|
|
*/
|
|
public static function isInstalledStandard($standard)
|
|
{
|
|
$path = self::getInstalledStandardPath($standard);
|
|
if ($path !== null && strpos($path, 'ruleset.xml') !== false) {
|
|
return true;
|
|
} else {
|
|
// This could be a custom standard, installed outside our
|
|
// standards directory.
|
|
$standard = Common::realPath($standard);
|
|
if ($standard === false) {
|
|
return false;
|
|
}
|
|
|
|
// Might be an actual ruleset file itUtil.
|
|
// If it has an XML extension, let's at least try it.
|
|
if (is_file($standard) === true
|
|
&& (substr(strtolower($standard), -4) === '.xml'
|
|
|| substr(strtolower($standard), -9) === '.xml.dist')
|
|
) {
|
|
return true;
|
|
}
|
|
|
|
// If it is a directory with a ruleset.xml file in it,
|
|
// it is a standard.
|
|
$ruleset = rtrim($standard, ' /\\').DIRECTORY_SEPARATOR.'ruleset.xml';
|
|
if (is_file($ruleset) === true) {
|
|
return true;
|
|
}
|
|
}//end if
|
|
|
|
return false;
|
|
|
|
}//end isInstalledStandard()
|
|
|
|
|
|
/**
|
|
* Return the path of an installed coding standard.
|
|
*
|
|
* Coding standards are directories located in the
|
|
* CodeSniffer/Standards directory. Valid coding standards
|
|
* include a ruleset.xml file.
|
|
*
|
|
* @param string $standard The name of the coding standard.
|
|
*
|
|
* @return string|null
|
|
*/
|
|
public static function getInstalledStandardPath($standard)
|
|
{
|
|
if (strpos($standard, '.') !== false) {
|
|
return null;
|
|
}
|
|
|
|
$installedPaths = self::getInstalledStandardPaths();
|
|
foreach ($installedPaths as $installedPath) {
|
|
$standardPath = $installedPath.DIRECTORY_SEPARATOR.$standard;
|
|
if (file_exists($standardPath) === false) {
|
|
if (basename($installedPath) !== $standard) {
|
|
continue;
|
|
}
|
|
|
|
$standardPath = $installedPath;
|
|
}
|
|
|
|
$path = Common::realpath($standardPath.DIRECTORY_SEPARATOR.'ruleset.xml');
|
|
|
|
if ($path !== false && is_file($path) === true) {
|
|
return $path;
|
|
} else if (Common::isPharFile($standardPath) === true) {
|
|
$path = Common::realpath($standardPath);
|
|
if ($path !== false) {
|
|
return $path;
|
|
}
|
|
}
|
|
}//end foreach
|
|
|
|
return null;
|
|
|
|
}//end getInstalledStandardPath()
|
|
|
|
|
|
/**
|
|
* Prints out a list of installed coding standards.
|
|
*
|
|
* @return void
|
|
*/
|
|
public static function printInstalledStandards()
|
|
{
|
|
$installedStandards = self::getInstalledStandards();
|
|
$numStandards = count($installedStandards);
|
|
|
|
if ($numStandards === 0) {
|
|
echo 'No coding standards are installed.'.PHP_EOL;
|
|
} else {
|
|
$lastStandard = array_pop($installedStandards);
|
|
if ($numStandards === 1) {
|
|
echo "The only coding standard installed is $lastStandard".PHP_EOL;
|
|
} else {
|
|
$standardList = implode(', ', $installedStandards);
|
|
$standardList .= ' and '.$lastStandard;
|
|
echo 'The installed coding standards are '.$standardList.PHP_EOL;
|
|
}
|
|
}
|
|
|
|
}//end printInstalledStandards()
|
|
|
|
|
|
}//end class
|