/**
  * 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;
 }