/** * Sets installed sniffs in the coding standard being used. * * Traverses the standard directory for classes that implement the * PHP_CodeSniffer_Sniff interface asks them to register. Each of the * sniff's class names must be exact as the basename of the sniff file. * If the standard is a file, will skip transversal and just load sniffs * from the file. * * @param string $standard The name of the coding standard we are checking. * Can also be a path to a custom standard dir * containing a ruleset.xml file or can be a path * to a custom ruleset file. * @param array $sniffs The sniff names to restrict the allowed * listeners to. * * @return void * @throws PHP_CodeSniffer_Exception If the standard is not valid. */ public function setTokenListeners($standard, array $sniffs = array()) { if (is_dir($standard) === true) { // This is an absolute path to a custom standard. self::$standardDir = $standard; $standard = basename($standard); } else { if (is_file($standard) === true) { // Might be a custom ruleset file. $ruleset = simplexml_load_file($standard); if ($ruleset === false) { throw new PHP_CodeSniffer_Exception("Ruleset {$standard} is not valid"); } if (basename($standard) === 'ruleset.xml') { // The ruleset uses the generic name, so this may actually // be a complete standard with it's own sniffs. By setting the // the standardDir to be the directory, we will process both // the directory (for custom sniffs) and the ruleset.xml file // (as it uses the generic name) in getSniffFiles. self::$standardDir = dirname($standard); } else { // This is a custom ruleset file with a custom name, so we have // to assume there are no custom sniffs to go with this otherwise // we'd be recursing through directories on every run, even if // we don't need to. self::$standardDir = $standard; } $standard = (string) $ruleset['name']; } else { self::$standardDir = realpath(dirname(__FILE__) . '/CodeSniffer/Standards/' . $standard); if (is_dir(self::$standardDir) === false) { // This isn't looking good. Let's see if this // is a relative path to a custom standard. $path = realpath(PHPCS_CWD . '/' . $standard); if (is_dir($path) === true) { // This is a relative path to a custom standard. self::$standardDir = $path; $standard = basename($standard); } else { if (is_file($path) === true) { // Might be a custom ruleset file. $ruleset = simplexml_load_file($path); if ($ruleset === false) { throw new PHP_CodeSniffer_Exception("Ruleset {$path} is not valid"); } // See comments in ELSE IF condition above for why we do this. if (basename($path) === 'ruleset.xml') { self::$standardDir = dirname($path); } else { self::$standardDir = $path; } $standard = (string) $ruleset['name']; } } } } } //end if $files = $this->getSniffFiles(self::$standardDir, $standard); if (empty($sniffs) === false) { // Convert the allowed sniffs to lower case so // they are easier to check. foreach ($sniffs as &$sniff) { $sniff = strtolower($sniff); } } $listeners = array(); foreach ($files as $file) { // Work out where the position of /StandardName/Sniffs/... is // so we can determine what the class will be called. $sniffPos = strrpos($file, DIRECTORY_SEPARATOR . 'Sniffs' . DIRECTORY_SEPARATOR); if ($sniffPos === false) { continue; } $slashPos = strrpos(substr($file, 0, $sniffPos), DIRECTORY_SEPARATOR); if ($slashPos === false) { continue; } $className = substr($file, $slashPos + 1); $className = substr($className, 0, -4); $className = str_replace(DIRECTORY_SEPARATOR, '_', $className); include_once $file; // If they have specified a list of sniffs to restrict to, check // to see if this sniff is allowed. $allowed = in_array(strtolower($className), $sniffs); if (empty($sniffs) === false && $allowed === false) { continue; } $listeners[] = $className; if (PHP_CODESNIFFER_VERBOSITY > 2) { echo "\tRegistered {$className}" . PHP_EOL; } } //end foreach $this->listeners = $listeners; }