#!/bin/php file as $filename => $file) { // Compile both warnings and errors into a list of sniffs. $file_sniffs = []; foreach ($file->error as $error) { $file_sniffs[] = (string) $error['source']; } foreach ($file->warning as $warning) { $file_sniffs[] = (string) $warning['source']; } foreach ($file_sniffs as $sniff) { // If the sniff granularity is 3 or higher, strip off the individual sniffs // and just keep the 'base sniff'. if (substr_count($sniff, '.') > 2) { $sniff = substr($sniff, 0, strrpos($sniff, '.')); } $sniffs[$sniff] = $sniff; } } $config = new PhpCodeSnifferConfiguration(); $config->setFiles('.'); $config->setExcludeSniffs($sniffs); $config->setExtensions('inc, info, install, module, php, profile, test, theme'); $config->setExcludePatterns([ [ 'comment' => 'Exclude third party code.', 'patterns' => [ './assets/vendor/*', './vendor/*', ], ], [ 'comment' => 'Exclude test files that are intentionally empty, or intentionally violate coding standards.', 'patterns' => [ './modules/system/tests/fixtures/HtaccessTest', ], ], [ 'comment' => 'Todo: remove this file. Ref. https://www.drupal.org/node/2575419', 'patterns' => [ './lib/Drupal/Core/Cache/Context/OriginalRequestCacheContext.php', ], ], ]); $config->main(); class PhpCodeSnifferConfiguration { /** * The path to the configuration file to generate. * * @var string */ protected $configFile = 'core/phpcs.xml.dist'; /** * The extensions to scan. * * @var array */ protected $extensions = []; /** * The list of files and folders to scan. * * @var array */ protected $files = []; /** * The list of patterns to exclude. * * @var array */ protected $excludePatterns = array(); /** * The list of sniffs to exclude. * * @var array */ protected $excludeSniffs = array(); /** * The report format to use. * * @var string */ protected $report = ''; /** * Whether or not to show progress. * * @var bool */ protected $showProgress = FALSE; /** * Whether or not to show sniff codes in the report. * * @var bool */ protected $showSniffCodes = FALSE; /** * The coding standard to use. * * @var string */ protected $standard; /** * Configures PHP CodeSniffer. */ public function main() { $document = new \DOMDocument('1.0', 'UTF-8'); $document->formatOutput = TRUE; // Create the root 'ruleset' element. $root_element = $document->createElement('ruleset'); $root_element->setAttribute('name', 'drupal_core'); $document->appendChild($root_element); // Add the description. $element = $document->createElement('description', 'Default PHP CodeSniffer configuration for Drupal core.'); $root_element->appendChild($element); // Add the files to check. foreach ($this->files as $file) { $element = $document->createElement('file', $file); $root_element->appendChild($element); } // Add file extensions. if (!empty($this->extensions)) { $extensions = implode(',', $this->extensions); $this->appendArgument($document, $root_element, $extensions, 'extensions'); } // Add exclude patterns. foreach ($this->excludePatterns as $data) { if (!empty($data['comment'])) { $element = $document->createComment($data['comment']); $root_element->appendChild($element); } foreach ($data['patterns'] as $pattern) { $element = $document->createElement('exclude-pattern', $pattern); $root_element->appendChild($element); } } // Exclude sniffs. $element = $document->createComment('Blacklist of coding standard rules that are not yet fixed. Ref. https://www.drupal.org/node/2571965'); $root_element->appendChild($element); $rule_element = $document->createElement('rule'); $rule_element->setAttribute('ref', 'Drupal'); foreach ($this->excludeSniffs as $sniff) { $element = $document->createElement('exclude'); $element->setAttribute('name', $sniff); $rule_element->appendChild($element); } $root_element->appendChild($rule_element); // Add the report type. if (!empty($this->report)) { $this->appendArgument($document, $root_element, $this->report, 'report'); } // Add the shorthand options. $shorthand_options = array( 'p' => 'showProgress', 's' => 'showSniffCodes', ); $options = array_filter($shorthand_options, function ($value) { return $this->$value; }); if (!empty($options)) { $this->appendArgument($document, $root_element, implode('', array_flip($options))); } echo($document->saveXML()); } /** * Appends an argument element to the XML document. * * This will append an XML element in the following format: * * * @param \DOMDocument $document * The document that will contain the argument to append. * @param \DOMElement $element * The parent element of the argument to append. * @param string $value * The argument value. * @param string $name * Optional argument name. */ protected function appendArgument(\DOMDocument $document, \DOMElement $element, $value, $name = '') { $argument = $document->createElement('arg'); if (!empty($name)) { $argument->setAttribute('name', $name); } $argument->setAttribute('value', $value); $element->appendChild($argument); } /** * Sets the path to the configuration file to generate. * * @param string $configFile * The path to the configuration file to generate. */ public function setConfigFile($configFile) { $this->configFile = $configFile; } /** * Sets the file extensions to scan. * * @param string $extensions * A string containing file extensions, delimited by spaces, commas or * semicolons. */ public function setExtensions($extensions) { $this->extensions = array(); $token = ' ,;'; $extension = strtok($extensions, $token); while ($extension !== FALSE) { $this->extensions[] = $extension; $extension = strtok($token); } } /** * Sets the list of files and folders to scan. * * @param string $files * A list of paths, delimited by spaces, commas or semicolons. */ public function setFiles($files) { $this->files = array(); $token = ' ,;'; $file = strtok($files, $token); while ($file !== FALSE) { $this->files[] = $file; $file = strtok($token); } } /** * Sets the list of patterns to exclude. * * @param string $excludePatterns * The list of patterns, delimited by spaces, commas or semicolons. */ public function setExcludePatterns($excludePatterns) { $this->excludePatterns = $excludePatterns; } /** * Sets the list of sniffs to exclude. * * @param string $sniffs * The list of sniffs to exclude. */ public function setExcludeSniffs($sniffs) { $sniffs = array_unique($sniffs); sort($sniffs); $this->excludeSniffs = $sniffs; } /** * Sets the report format to use. * * @param string $report * The report format to use. */ public function setReport($report) { $this->report = $report; } /** * Sets whether or not to show progress. * * @param bool $showProgress * Whether or not to show progress. */ public function setShowProgress($showProgress) { $this->showProgress = (bool) $showProgress; } /** * Sets whether or not to show sniff codes in the report. * * @param bool $showSniffCodes * Whether or not to show sniff codes. */ public function setShowSniffCodes($showSniffCodes) { $this->showSniffCodes = (bool) $showSniffCodes; } /** * Sets the coding standard to use. * * @param string $standard * The coding standard to use. */ public function setStandard($standard) { $this->standard = $standard; } }