From 7326ab7a4edace69c3d3a72081408a2f582cb792 Mon Sep 17 00:00:00 2001 From: "andy.grunwald" Date: Thu, 19 Apr 2012 23:21:58 +0200 Subject: [PATCH] [FEATURE] Add support to import namespaces for sniffs During the development of sniffs for the CMS TYPO3 and the framework FLOW3 we create some own codesniffs. Out folder structure looks like: |-TYPO3 |--Sniffs |-TYPO3v4 |--ruleset.xml |-FLOW3 |--ruleset.xml Folder TYPO3 contains all sniffs. TYPO3v4 and FLOW3 implement only a subset of the sniffs, which are located in FLOW3. At the moment we have to symlink the TYPO3-Folder into the PHP_CodeSniffer standard directory to use this. This is not a nice solution. This commit try to fix this problem. This commit introduces to import sniff namespaces. Imagine you add your rules like If there is no symlink in your standard directory for TYPO3 an exception will be thrown. With this commit you have the possibility to import the namespace TYPO3 like Now the TYPO3 standard is known without symlinking :) --- CodeSniffer.php | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/CodeSniffer.php b/CodeSniffer.php index d11b0466c2..07d0335896 100644 --- a/CodeSniffer.php +++ b/CodeSniffer.php @@ -135,6 +135,13 @@ class PHP_CodeSniffer */ protected $ignorePatterns = array(); + /** + * An array of imported namespaces + * + * @var array + */ + protected $importedNamespaces = array(); + /** * An array of extensions for files we will check. * @@ -736,6 +743,9 @@ public function getSniffFiles($dir, $standard=null) throw new PHP_CodeSniffer_Exception("Ruleset $rulesetPath is not valid"); } + // Load imported namespaces for relative standards + $this->loadImportedNamespaces($dir, $ruleset); + foreach ($ruleset->rule as $rule) { $includedSniffs = array_merge($includedSniffs, $this->_expandRulesetReference($rule['ref'])); @@ -766,6 +776,36 @@ public function getSniffFiles($dir, $standard=null) }//end getSniffFiles() + /** + * Load namespaces for sniffs which are not located as installed sniff. + * + * @param string $dir The directory where to look for the files. + * @param SimpleXMLElement $ruleset The ruleset xml of standard + * + * @return void + */ + protected function loadImportedNamespaces($dir, SimpleXMLElement $ruleset) { + // If there are no namespace imports, exit right here + if(property_exists($ruleset, 'namespace-import') !== true) { + return; + } + + // Import the namespaces + foreach ($ruleset->{'namespace-import'} as $ruleImport) { + $importedRulePath = $ruleImport['ref']; + + // If an imported rule starts with / already is fine, because there is a absolute path + // If it starts with "../" the imported rule is relative to the ruleset.xml + if(substr($importedRulePath, 0, 3) === '../') { + $importedRulePath = realpath($dir . '/' . $importedRulePath); + } + + if(is_dir($importedRulePath) === true) { + $this->importedNamespaces[(string) $ruleImport['name']] = $importedRulePath; + } + } + }//end loadImportedNamespaces() + /** * Expand a ruleset sniff reference into a list of sniff files. * @@ -813,6 +853,11 @@ private function _expandRulesetReference($sniff) // installed in there. $path = realpath(self::$standardDir.'/Sniffs/'.$parts[1].'/'.$parts[2].'Sniff.php'); } + + // If there was no standard found, have a look at the namespace import + if ($path === false && isset($this->importedNamespaces[$parts[0]])) { + $path = realpath($this->importedNamespaces[$parts[0]].'/Sniffs/'.$parts[1].'/'.$parts[2].'Sniff.php'); + } } }//end if