Coding standards are directories located in the
CodeSniffer/Standards directory. Valid coding standards
include a ruleset.xml file.
public static isInstalledStandard ( string $standard ) : boolean | ||
$standard | string | The name of the coding standard. |
리턴 | boolean |
/** * Convert the passed standard into a valid standard. * * Checks things like default values and case. * * @param string $standard The standard to validate. * * @return string */ public function validateStandard($standard) { if ($standard === null) { // They did not supply a standard to use. // Try to get the default from the config system. $standard = PHP_CodeSniffer::getConfigData('default_standard'); if ($standard === null) { $standard = 'PEAR'; } } // Check if the standard name is valid. If not, check that the case // was not entered incorrectly. if (PHP_CodeSniffer::isInstalledStandard($standard) === false) { $installedStandards = PHP_CodeSniffer::getInstalledStandards(); foreach ($installedStandards as $validStandard) { if (strtolower($standard) === strtolower($validStandard)) { $standard = $validStandard; break; } } } return $standard; }
/** * Executes PHP code sniffer against PhingFile or a FileSet */ public function main() { if (!class_exists('PHP_CodeSniffer')) { @(include_once 'PHP/CodeSniffer.php'); if (!class_exists('PHP_CodeSniffer')) { throw new BuildException("This task requires the PHP_CodeSniffer package installed and available on the include path", $this->getLocation()); } } /** * Determine PHP_CodeSniffer version number */ if (!$this->skipversioncheck) { if (defined('PHP_CodeSniffer::VERSION')) { preg_match('/\\d\\.\\d\\.\\d/', PHP_CodeSniffer::VERSION, $version); } else { preg_match('/\\d\\.\\d\\.\\d/', shell_exec('phpcs --version'), $version); } if (version_compare($version[0], '1.2.2') < 0) { throw new BuildException('PhpCodeSnifferTask requires PHP_CodeSniffer version >= 1.2.2', $this->getLocation()); } } if (!isset($this->file) and count($this->filesets) == 0) { throw new BuildException("Missing either a nested fileset or attribute 'file' set"); } if (count($this->formatters) == 0) { // turn legacy format attribute into formatter $fmt = new PhpCodeSnifferTask_FormatterElement(); $fmt->setType($this->format); $fmt->setUseFile(false); $this->formatters[] = $fmt; } $fileList = array(); if (!isset($this->file)) { $project = $this->getProject(); foreach ($this->filesets as $fs) { $ds = $fs->getDirectoryScanner($project); $files = $ds->getIncludedFiles(); $dir = $fs->getDir($this->project)->getAbsolutePath(); foreach ($files as $file) { $fileList[] = $dir . DIRECTORY_SEPARATOR . $file; } } } else { $fileList[] = $this->file->getPath(); } $cwd = getcwd(); // Save command line arguments because it confuses PHPCS (version 1.3.0) $oldArgs = $_SERVER['argv']; $_SERVER['argv'] = array(); $_SERVER['argc'] = 0; include_once 'phing/tasks/ext/phpcs/PhpCodeSnifferTask_Wrapper.php'; $codeSniffer = new PhpCodeSnifferTask_Wrapper($this->verbosity, $this->tabWidth, $this->encoding); $codeSniffer->setAllowedFileExtensions($this->allowedFileExtensions); if ($this->allowedTypes) { PhpCodeSnifferTask_Wrapper::$allowedTypes = $this->allowedTypes; } if (is_array($this->ignorePatterns)) { $codeSniffer->setIgnorePatterns($this->ignorePatterns); } foreach ($this->configData as $configData) { $codeSniffer->setConfigData($configData->getName(), $configData->getValue(), true); } /* * Verifying if standard is installed only after setting config data. * Custom standard paths could be provided via installed_paths config parameter. */ foreach ($this->standards as $standard) { if (PHP_CodeSniffer::isInstalledStandard($standard) === false) { // They didn't select a valid coding standard, so help them // out by letting them know which standards are installed. $installedStandards = PHP_CodeSniffer::getInstalledStandards(); $numStandards = count($installedStandards); $errMsg = ''; if ($numStandards === 0) { $errMsg = 'No coding standards are installed.'; } else { $lastStandard = array_pop($installedStandards); if ($numStandards === 1) { $errMsg = 'The only coding standard installed is ' . $lastStandard; } else { $standardList = implode(', ', $installedStandards); $standardList .= ' and ' . $lastStandard; $errMsg = 'The installed coding standards are ' . $standardList; } } throw new BuildException('ERROR: the "' . $standard . '" coding standard is not installed. ' . $errMsg, $this->getLocation()); } } if (!$this->showWarnings) { $codeSniffer->cli->warningSeverity = 0; } // nasty integration hack $values = $codeSniffer->cli->getDefaults(); $_SERVER['argv'] = array('t'); $_SERVER['argc'] = 1; foreach ($this->formatters as $fe) { $output = $fe->getUseFile() ? $fe->getOutFile() : null; $_SERVER['argv'][] = '--report-' . $fe->getType() . '=' . $output; $_SERVER['argc']++; } $codeSniffer->process($fileList, $this->standards, $this->sniffs, $this->noSubdirectories); $_SERVER['argv'] = array(); $_SERVER['argc'] = 0; $this->printErrorReport($codeSniffer); // generate the documentation if ($this->docGenerator !== '' && $this->docFile !== null) { ob_start(); $codeSniffer->generateDocs($this->standards, $this->sniffs, $this->docGenerator); $output = ob_get_contents(); ob_end_clean(); // write to file $outputFile = $this->docFile->getPath(); $check = file_put_contents($outputFile, $output); if (is_bool($check) && !$check) { throw new BuildException('Error writing doc to ' . $outputFile); } } elseif ($this->docGenerator !== '' && $this->docFile === null) { $codeSniffer->generateDocs($this->standards, $this->sniffs, $this->docGenerator); } if ($this->haltonerror && $codeSniffer->reporting->totalErrors > 0) { throw new BuildException('phpcodesniffer detected ' . $codeSniffer->reporting->totalErrors . ' error' . ($codeSniffer->reporting->totalErrors > 1 ? 's' : '')); } if ($this->haltonwarning && $codeSniffer->reporting->totalWarnings > 0) { throw new BuildException('phpcodesniffer detected ' . $codeSniffer->reporting->totalWarnings . ' warning' . ($codeSniffer->reporting->totalWarnings > 1 ? 's' : '')); } $_SERVER['argv'] = $oldArgs; $_SERVER['argc'] = count($oldArgs); chdir($cwd); }
/** * Runs PHP_CodeSniffer over files and directories. * * @param array $values An array of values determined from CLI args. * * @return int The number of error and warning messages shown. * @see getCommandLineValues() */ public function process($values = array()) { if (empty($values) === true) { $values = $this->getCommandLineValues(); } else { $values = array_merge($this->getDefaults(), $values); $this->values = $values; } if ($values['generator'] !== '') { $phpcs = new PHP_CodeSniffer($values['verbosity']); if ($values['standard'] === null) { $values['standard'] = $this->validateStandard(null); } foreach ($values['standard'] as $standard) { $phpcs->generateDocs($standard, $values['sniffs'], $values['generator']); } exit(0); } // If no standard is supplied, get the default. $values['standard'] = $this->validateStandard($values['standard']); foreach ($values['standard'] as $standard) { if (PHP_CodeSniffer::isInstalledStandard($standard) === false) { // They didn't select a valid coding standard, so help them // out by letting them know which standards are installed. echo 'ERROR: the "' . $standard . '" coding standard is not installed. '; $this->printInstalledStandards(); exit(2); } } if ($values['explain'] === true) { foreach ($values['standard'] as $standard) { $this->explainStandard($standard); } exit(0); } $phpcs = new PHP_CodeSniffer($values['verbosity'], null, null, null); $phpcs->setCli($this); $phpcs->initStandard($values['standard'], $values['sniffs']); $values = $this->values; $phpcs->setTabWidth($values['tabWidth']); $phpcs->setEncoding($values['encoding']); $phpcs->setInteractive($values['interactive']); // Set file extensions if they were specified. Otherwise, // let PHP_CodeSniffer decide on the defaults. if (empty($values['extensions']) === false) { $phpcs->setAllowedFileExtensions($values['extensions']); } // Set ignore patterns if they were specified. if (empty($values['ignored']) === false) { $ignorePatterns = array_merge($phpcs->getIgnorePatterns(), $values['ignored']); $phpcs->setIgnorePatterns($ignorePatterns); } // Set some convenience member vars. if ($values['errorSeverity'] === null) { $this->errorSeverity = PHPCS_DEFAULT_ERROR_SEV; } else { $this->errorSeverity = $values['errorSeverity']; } if ($values['warningSeverity'] === null) { $this->warningSeverity = PHPCS_DEFAULT_WARN_SEV; } else { $this->warningSeverity = $values['warningSeverity']; } if (empty($values['reports']) === true) { $values['reports']['full'] = $values['reportFile']; $this->values['reports'] = $values['reports']; } // Include bootstrap files. foreach ($values['bootstrap'] as $bootstrap) { include $bootstrap; } $phpcs->processFiles($values['files'], $values['local']); if (empty($values['files']) === true || $values['stdin'] !== null) { $fileContents = $values['stdin']; if ($fileContents === null) { // Check if they are passing in the file contents. $handle = fopen('php://stdin', 'r'); stream_set_blocking($handle, true); $fileContents = stream_get_contents($handle); fclose($handle); } if ($fileContents === '') { // No files and no content passed in. echo 'ERROR: You must supply at least one file or directory to process.' . PHP_EOL . PHP_EOL; $this->printUsage(); exit(2); } else { $phpcs->processFile('STDIN', $fileContents); } } // Interactive runs don't require a final report and it doesn't really // matter what the retun value is because we know it isn't being read // by a script. if ($values['interactive'] === true) { return 0; } return $this->printErrorReport($phpcs, $values['reports'], $values['showSources'], $values['reportFile'], $values['reportWidth']); }
/** * Runs PHP_CodeSniffer over files and directories. * * @param array $values An array of values determined from CLI args. * @return array Returns list of errors/warnings * @throws \Exception * @throws \PHP_CodeSniffer_Exception * @see \PHP_CodeSniffer_CLI::getCommandLineValues() * @see \PHP_CodeSniffer_CLI::process() */ public function process($values = array()) { if (empty($values) === true) { $values = $this->getCommandLineValues(); } else { $values = array_merge($this->getDefaults(), $values); $this->values = $values; } if ($values['generator'] !== '') { throw new Exception('This parameter is not supported.'); } // If no standard is supplied, get the default. $values['standard'] = $this->validateStandard($values['standard']); foreach ($values['standard'] as $standard) { if (\PHP_CodeSniffer::isInstalledStandard($standard) === false) { // They didn't select a valid coding standard, so help them // out by letting them know which standards are installed. throw new \PHP_CodeSniffer_Exception('ERROR: the "' . $standard . '" coding standard is not installed.'); } } $phpcs = $this->getSniffer($values); $phpcs->setCli($this); $phpcs->initStandard($values['standard'], $values['sniffs']); $values = $this->values; $phpcs->setTabWidth($values['tabWidth']); $phpcs->setEncoding($values['encoding']); $phpcs->setInteractive($values['interactive']); // Set file extensions if they were specified. Otherwise, // let PHP_CodeSniffer decide on the defaults. if (empty($values['extensions']) === false) { $phpcs->setAllowedFileExtensions($values['extensions']); } // Set ignore patterns if they were specified. if (empty($values['ignored']) === false) { $ignorePatterns = array_merge($phpcs->getIgnorePatterns(), $values['ignored']); $phpcs->setIgnorePatterns($ignorePatterns); } // Set some convenience member vars. if ($values['errorSeverity'] === null) { $this->errorSeverity = PHPCS_DEFAULT_ERROR_SEV; } else { $this->errorSeverity = $values['errorSeverity']; } if ($values['warningSeverity'] === null) { $this->warningSeverity = PHPCS_DEFAULT_WARN_SEV; } else { $this->warningSeverity = $values['warningSeverity']; } if (empty($values['reports']) === true) { $values['reports']['full'] = $values['reportFile']; $this->values['reports'] = $values['reports']; } $result = $phpcs->processFiles($values['files'], $values['local']); if (empty($values['files']) === true) { // Check if they are passing in the file contents. $handle = fopen('php://stdin', 'r'); $fileContents = stream_get_contents($handle); fclose($handle); if ($fileContents === '') { // No files and no content passed in. throw new \Exception('ERROR: You must supply at least one file or directory to process.'); } else { if ($fileContents !== '') { $phpcs->processFile('STDIN', $fileContents); } } } // Interactive runs don't require a final report and it doesn't really // matter what the return value is because we know it isn't being read // by a script. if ($values['interactive'] === true) { return array(); } return $result; }
/** * Sets the coding standard to test for * * @param string $standard The coding standard * * @return void */ public function setStandard($standard) { if (!class_exists('PHP_CodeSniffer')) { include_once 'PHP/CodeSniffer.php'; } if (PHP_CodeSniffer::isInstalledStandard($standard) === false) { // They didn't select a valid coding standard, so help them // out by letting them know which standards are installed. $installedStandards = PHP_CodeSniffer::getInstalledStandards(); $numStandards = count($installedStandards); $errMsg = ''; if ($numStandards === 0) { $errMsg = 'No coding standards are installed.'; } else { $lastStandard = array_pop($installedStandards); if ($numStandards === 1) { $errMsg = 'The only coding standard installed is ' . $lastStandard; } else { $standardList = implode(', ', $installedStandards); $standardList .= ' and ' . $lastStandard; $errMsg = 'The installed coding standards are ' . $standardList; } } throw new BuildException('ERROR: the "' . $standard . '" coding standard is not installed. ' . $errMsg, $this->getLocation()); } $this->standard = $standard; }
private function process($files, $interactive = true) { $standards = 'Webasyst'; if (PHP_CodeSniffer::isInstalledStandard($standards) === false) { $this->tracef('WARNING: %s standard not found, will used PSR2. Some rules are differ', $standards); $standards = 'PSR2'; } if (is_array($standards) === false) { $standards = array($standards); } $phpcs = new PHP_CodeSniffer(0, 4, 'UTF-8', $interactive); // Set file extensions if they were specified. Otherwise, // let PHP_CodeSniffer decide on the defaults. if (true) { $extensions = array('php', 'js', 'css'); $phpcs->setAllowedFileExtensions($extensions); } if (is_array($files) === false) { $files = array($files); } // Reset the members. // Ensure this option is enabled or else line endings will not always // be detected properly for files created on a Mac with the /r line ending. ini_set('auto_detect_line_endings', true); $sniffs = array(); foreach ($standards as $standard) { $installed = $phpcs->getInstalledStandardPath($standard); if ($installed !== null) { $standard = $installed; } else { if (is_dir($standard) === true && is_file(realpath($standard . '/ruleset.xml')) === true) { $standard = realpath($standard . '/ruleset.xml'); } } $sniffs = array_merge($sniffs, $phpcs->processRuleset($standard)); } //end foreach $sniffRestrictions = array(); $phpcs->registerSniffs($sniffs, $sniffRestrictions); $phpcs->populateTokenListeners(); // The SVN pre-commit calls process() to init the sniffs // and ruleset so there may not be any files to process. // But this has to come after that initial setup. //define('PHP_CODESNIFFER_IN_TESTS',true); $_SERVER['argc'] = 0; $errors_count = 0; foreach ($files as $file) { $phpcsFile = $phpcs->processFile($file); // Show progress information. if ($phpcsFile !== null) { $count = $phpcsFile->getErrorCount() + $phpcsFile->getWarningCount(); if (!$interactive && $count) { $report = array('ERROR' => $phpcsFile->getErrors(), 'WARNING' => $phpcsFile->getWarnings()); $this->tracef("\nFILE: %s", str_replace($this->path . '/', '', $file)); $this->trace(str_repeat('-', 80)); foreach ($report as $type => $errors) { foreach ($errors as $line => $line_errors) { foreach ($line_errors as $column => $errors) { foreach ($errors as $error) { $this->tracef('%4d | %s | %s', $line, $type, $error['message']); } } } } $this->trace(str_repeat('-', 80)); } $errors_count += $count; } } return $errors_count; }
/** * @link http://www.webasyst.ru/developers/docs/basics/naming-rules/ */ private function codeStyle($param) { error_reporting(E_ALL | E_STRICT); $files = array(); $ext = array('php', 'js', 'html', 'css'); foreach ($this->files as $file) { if (in_array(pathinfo($file, PATHINFO_EXTENSION), $ext)) { if ($param === 'vendors' && preg_match('@^(lib/)?vendors/@', $file)) { continue; } if (preg_match('@\\.min\\.(js|css)$@', $file)) { continue; } $files[] = $this->path . '/' . $file; } } include_once 'PHP/CodeSniffer.php'; if (!class_exists('PHP_CodeSniffer')) { $this->trace('WARNING: Code style check skipped:'); $this->trace(' PEAR extension CodeSniffer required'); return; } $values = array('verbosity' => 0, 'tabWidth' => 4, 'encoding' => 'UTF-8', 'interactive' => true, 'files' => $files, 'standard' => 'Webasyst', 'sniffs' => array(), 'local' => true, 'reports' => array('full' => null), 'extensions' => array('php', 'html', 'js', 'css')); if (PHP_CodeSniffer::isInstalledStandard($values['standard']) === false) { $this->tracef('WARNING: %s standard not found, will used PSR2. Some rules are differ', $values['standard']); $values['standard'] = 'PSR2'; } $phpcs = new PHP_CodeSniffer($values['verbosity'], $values['tabWidth'], $values['encoding'], $values['interactive']); // Set file extensions if they were specified. Otherwise, // let PHP_CodeSniffer decide on the defaults. if (empty($values['extensions']) === false) { $phpcs->setAllowedFileExtensions($values['extensions']); } try { $phpcs->process($values['files'], $values['standard'], $values['sniffs'], $values['local']); } catch (Exception $ex) { $this->tracef('ERROR: %s', $ex->getMessage()); } }
/** * Return a list of sniffs that a coding standard has defined. * * Sniffs are found by recursing the standard directory and also by * asking the standard for included sniffs. * * @param string $dir The directory where to look for the files. * @param string $standard The name of the coding standard. If NULL, no * included sniffs will be checked for. * * @return array * @throws Exception If there was an error opening the directory. */ private function _getSniffFiles($dir, $standard = null) { $di = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir)); $files = array(); foreach ($di as $file) { // Skip hidden files. if (substr($file->getFilename(), 0, 1) === '.') { continue; } // We are only interested in PHP and sniff files. $fileParts = explode('.', $file); if (array_pop($fileParts) !== 'php') { continue; } $basename = basename($file, '.php'); if (substr($basename, -5) !== 'Sniff') { continue; } $files[] = $file->getPathname(); } // Load the standard class and ask it for a list of external // sniffs to include in the standard. if ($standard !== null && is_file("{$dir}/{$standard}CodingStandard.php") === true) { include_once "{$dir}/{$standard}CodingStandard.php"; $standardClassName = "PHP_CodeSniffer_Standards_{$standard}_{$standard}CodingStandard"; $standardClass = new $standardClassName(); $includedSniffs = $standardClass->getIncludedSniffs(); foreach ($includedSniffs as $sniff) { $sniffDir = realpath(dirname(__FILE__) . "/CodeSniffer/Standards/{$sniff}"); if (is_dir($sniffDir) === true) { if (PHP_CodeSniffer::isInstalledStandard($sniff) === true) { // We are including a whole coding standard. $files += $this->_getSniffFiles($sniffDir, $sniff); } else { // We are including a whole directory of sniffs. $files += $this->_getSniffFiles($sniffDir); } } else { if (substr($sniffDir, -5) !== 'Sniff') { continue; } $files[] = "{$sniffDir}.php"; } } } //end if return $files; }
/** * Execute the task * * @return self * @throw BuildException */ public function execute() { if (!$this->getStandard()) { throw new BuildException("No standard set"); } if (!class_exists("CodeSniffer")) { Pale::run(function () { require_once "PHP/CodeSniffer.php"; }); } if (CodeSniffer::isInstalledStandard($this->getStandard()) === false) { throw new BuildException("Invalid standard name"); } // Clear out argv so PHP_CodeSniffer doesn"t freak out $oldArgv = $SERVER["argv"]; $SERVER["argv"] = array(); $SERVER["argc"] = 0; // Get the current working directory because PHP_CodeSniffer will change it $cwd = getcwd(); $codeSniffer = new CodeSniffer(0, 0, "UTF-8"); $codeSniffer->process($this->getFiles(), $this->filterProperties($this->getStandard())); // Restore the argv/c superglobals $SERVER["argv"] = $oldArgv; $SERVER["argc"] = count($oldArgv); // Reset the current working directory chdir($cwd); $filesViolations = $codeSniffer->getFilesErrors(); $reporting = new Reporting(); $report = $reporting->prepare($filesViolations, $this->getShowWarnings()); $reporting->printReport($this->getReportType(), $filesViolations, $this->getShowSources(), $this->getReportFile(), $this->getReportWidth()); return $this; }