Example #1
0
 /**
  * Checks filtering rules to see if a path should be ignored.
  *
  * @param string $path The path to the file or directory being checked.
  *
  * @return bool
  */
 protected function shouldIgnorePath($path)
 {
     if ($this->ignoreFilePatterns === null) {
         $this->ignoreDirPatterns = array();
         $this->ignoreFilePatterns = array();
         $ignorePatterns = array_merge($this->config->ignored, $this->ruleset->getIgnorePatterns());
         foreach ($ignorePatterns as $pattern => $type) {
             // If the ignore pattern ends with /* then it is ignoring an entire directory.
             if (substr($pattern, -2) === '/*') {
                 $this->ignoreDirPatterns[substr($pattern, 0, -2)] = $type;
             } else {
                 $this->ignoreFilePatterns[$pattern] = $type;
             }
         }
     }
     $relativePath = $path;
     if (strpos($path, $this->basedir) === 0) {
         // The +1 cuts off the directory separator as well.
         $relativePath = substr($path, strlen($this->basedir) + 1);
     }
     if (is_dir($path) === true) {
         $ignorePatterns = $this->ignoreDirPatterns;
     } else {
         $ignorePatterns = $this->ignoreFilePatterns;
     }
     foreach ($ignorePatterns as $pattern => $type) {
         // Maintains backwards compatibility in case the ignore pattern does
         // not have a relative/absolute value.
         if (is_int($pattern) === true) {
             $pattern = $type;
             $type = 'absolute';
         }
         $replacements = array('\\,' => ',', '*' => '.*');
         // We assume a / directory separator, as do the exclude rules
         // most developers write, so we need a special case for any system
         // that is different.
         if (DIRECTORY_SEPARATOR === '\\') {
             $replacements['/'] = '\\\\';
         }
         $pattern = strtr($pattern, $replacements);
         if ($type === 'relative') {
             $testPath = $relativePath;
         } else {
             $testPath = $path;
         }
         $pattern = '`' . $pattern . '`i';
         if (preg_match($pattern, $testPath) === 1) {
             return true;
         }
     }
     //end foreach
     return false;
 }
Example #2
0
 /**
  * Starts the stack traversal and tells listeners when tokens are found.
  *
  * @return void
  */
 public function process()
 {
     if ($this->ignored === true) {
         return;
     }
     $this->errors = array();
     $this->warnings = array();
     $this->errorCount = 0;
     $this->warningCount = 0;
     $this->fixableCount = 0;
     $this->parse();
     $this->fixer->startFile($this);
     if (PHP_CODESNIFFER_VERBOSITY > 2) {
         echo "\t*** START TOKEN PROCESSING ***" . PHP_EOL;
     }
     $foundCode = false;
     $listenerIgnoreTo = array();
     $inTests = defined('PHP_CODESNIFFER_IN_TESTS');
     // Foreach of the listeners that have registered to listen for this
     // token, get them to process it.
     foreach ($this->tokens as $stackPtr => $token) {
         // Check for ignored lines.
         if ($token['code'] === T_COMMENT || $token['code'] === T_DOC_COMMENT_TAG || $inTests === true && $token['code'] === T_INLINE_HTML) {
             if (strpos($token['content'], '@codingStandards') !== false) {
                 if (strpos($token['content'], '@codingStandardsIgnoreFile') !== false) {
                     // Ignoring the whole file, just a little late.
                     $this->errors = array();
                     $this->warnings = array();
                     $this->errorCount = 0;
                     $this->warningCount = 0;
                     $this->fixableCount = 0;
                     return;
                 } else {
                     if (strpos($token['content'], '@codingStandardsChangeSetting') !== false) {
                         $start = strpos($token['content'], '@codingStandardsChangeSetting');
                         $comment = substr($token['content'], $start + 30);
                         $parts = explode(' ', $comment);
                         if ($parts >= 3) {
                             $sniffParts = explode('.', $parts[0]);
                             if ($sniffParts >= 3) {
                                 // If the sniff code is not know to us, it has not been registered in this run.
                                 // But don't throw an error as it could be there for a different standard to use.
                                 if (isset($this->ruleset->sniffCodes[$parts[0]]) === true) {
                                     $listenerCode = array_shift($parts);
                                     $propertyCode = array_shift($parts);
                                     $propertyValue = rtrim(implode(' ', $parts), " */\r\n");
                                     $listenerClass = $this->ruleset->sniffCodes[$listenerCode];
                                     $this->ruleset->setSniffProperty($listenerClass, $propertyCode, $propertyValue);
                                 }
                             }
                         }
                     }
                 }
                 //end if
             }
             //end if
         }
         //end if
         if (PHP_CODESNIFFER_VERBOSITY > 2) {
             $type = $token['type'];
             $content = Util\Common::prepareForOutput($token['content']);
             echo "\t\tProcess token {$stackPtr}: {$type} => {$content}" . PHP_EOL;
         }
         if ($token['code'] !== T_INLINE_HTML) {
             $foundCode = true;
         }
         if (isset($this->ruleset->tokenListeners[$token['code']]) === false) {
             continue;
         }
         foreach ($this->ruleset->tokenListeners[$token['code']] as $listenerData) {
             if (isset($this->ignoredListeners[$listenerData['class']]) === true || isset($listenerIgnoreTo[$listenerData['class']]) === true && $listenerIgnoreTo[$listenerData['class']] > $stackPtr) {
                 // This sniff is ignoring past this token, or the whole file.
                 continue;
             }
             // Make sure this sniff supports the tokenizer
             // we are currently using.
             $class = $listenerData['class'];
             if (isset($listenerData['tokenizers'][$this->tokenizerType]) === false) {
                 continue;
             }
             // If the file path matches one of our ignore patterns, skip it.
             // While there is support for a type of each pattern
             // (absolute or relative) we don't actually support it here.
             foreach ($listenerData['ignore'] as $pattern) {
                 // We assume a / directory separator, as do the exclude rules
                 // most developers write, so we need a special case for any system
                 // that is different.
                 if (DIRECTORY_SEPARATOR === '\\') {
                     $pattern = str_replace('/', '\\\\', $pattern);
                 }
                 $pattern = '`' . $pattern . '`i';
                 if (preg_match($pattern, $this->path) === 1) {
                     $this->ignoredListeners[$class] = true;
                     continue 2;
                 }
             }
             // If the file path does not match one of our include patterns, skip it.
             // While there is support for a type of each pattern
             // (absolute or relative) we don't actually support it here.
             foreach ($listenerData['include'] as $pattern) {
                 // We assume a / directory separator, as do the exclude rules
                 // most developers write, so we need a special case for any system
                 // that is different.
                 if (DIRECTORY_SEPARATOR === '\\') {
                     $pattern = str_replace('/', '\\\\', $pattern);
                 }
                 $pattern = '`' . $pattern . '`i';
                 if (preg_match($pattern, $this->path) !== 1) {
                     $this->ignoredListeners[$class] = true;
                     continue 2;
                 }
             }
             $this->activeListener = $class;
             if (PHP_CODESNIFFER_VERBOSITY > 2) {
                 $startTime = microtime(true);
                 echo "\t\t\tProcessing " . $this->activeListener . '... ';
             }
             $ignoreTo = $this->ruleset->sniffs[$class]->process($this, $stackPtr);
             if ($ignoreTo !== null) {
                 $listenerIgnoreTo[$this->activeListener] = $ignoreTo;
             }
             if (PHP_CODESNIFFER_VERBOSITY > 2) {
                 $timeTaken = microtime(true) - $startTime;
                 if (isset($this->listenerTimes[$this->activeListener]) === false) {
                     $this->listenerTimes[$this->activeListener] = 0;
                 }
                 $this->listenerTimes[$this->activeListener] += $timeTaken;
                 $timeTaken = round($timeTaken, 4);
                 echo "DONE in {$timeTaken} seconds" . PHP_EOL;
             }
             $this->activeListener = '';
         }
         //end foreach
     }
     //end foreach
     // If short open tags are off but the file being checked uses
     // short open tags, the whole content will be inline HTML
     // and nothing will be checked. So try and handle this case.
     if ($foundCode === false && $this->tokenizerType === 'PHP') {
         $shortTags = (bool) ini_get('short_open_tag');
         if ($shortTags === false) {
             $error = 'No PHP code was found in this file and short open tags are not allowed by this install of PHP. This file may be using short open tags but PHP does not allow them.';
             $this->addWarning($error, null, 'Internal.NoCodeFound');
         }
     }
     if (PHP_CODESNIFFER_VERBOSITY > 2) {
         echo "\t*** END TOKEN PROCESSING ***" . PHP_EOL;
         echo "\t*** START SNIFF PROCESSING REPORT ***" . PHP_EOL;
         asort($this->listenerTimes, SORT_NUMERIC);
         $this->listenerTimes = array_reverse($this->listenerTimes, true);
         foreach ($this->listenerTimes as $listener => $timeTaken) {
             echo "\t{$listener}: " . round($timeTaken, 4) . ' secs' . PHP_EOL;
         }
         echo "\t*** END SNIFF PROCESSING REPORT ***" . PHP_EOL;
     }
     $this->fixedCount += $this->fixer->getFixCount();
 }
Example #3
0
 /**
  * Run the PHPCS script.
  *
  * @return array
  */
 public function runPHPCS()
 {
     Util\Timing::startTiming();
     Runner::checkRequirements();
     if (defined('PHP_CODESNIFFER_CBF') === false) {
         define('PHP_CODESNIFFER_CBF', false);
     }
     // Creating the Config object populates it with all required settings
     // based on the CLI arguments provided to the script and any config
     // values the user has set.
     $this->config = new Config();
     // Init the run and load the rulesets to set additional config vars.
     $this->init();
     // Print a list of sniffs in each of the supplied standards.
     // We fudge the config here so that each standard is explained in isolation.
     if ($this->config->explain === true) {
         $standards = $this->config->standards;
         foreach ($standards as $standard) {
             $this->config->standards = array($standard);
             $ruleset = new Ruleset($this->config);
             $ruleset->explain();
         }
         exit(0);
     }
     // Generate documentation for each of the supplied standards.
     if ($this->config->generator !== null) {
         $standards = $this->config->standards;
         foreach ($standards as $standard) {
             $this->config->standards = array($standard);
             $ruleset = new Ruleset($this->config);
             $class = 'PHP_CodeSniffer\\Generators\\' . $this->config->generator;
             $generator = new $class($ruleset);
             $generator->generate();
         }
         exit(0);
     }
     // Other report formats don't really make sense in interactive mode
     // so we hard-code the full report here and when outputting.
     // We also ensure parallel processing is off because we need to do one file at a time.
     if ($this->config->interactive === true) {
         $this->config->reports = array('full' => null);
         $this->config->parallel = 1;
         $this->config->showProcess = false;
     }
     // Disable caching if we are processing STDIN as we can't be 100%
     // sure where the file came from or if it will change in the future.
     if ($this->config->stdin === true) {
         $this->config->cache = false;
     }
     $numErrors = $this->run();
     // Print all the reports for this run.
     $toScreen = $this->reporter->printReports();
     // Only print timer output if no reports were
     // printed to the screen so we don't put additional output
     // in something like an XML report. If we are printing to screen,
     // the report types would have already worked out who should
     // print the timer info.
     if ($this->config->interactive === false && ($toScreen === false || $this->reporter->totalErrors + $this->reporter->totalWarnings === 0 && $this->config->showProgress === true)) {
         Util\Timing::printRunTime();
     }
     if ($numErrors === 0) {
         // No errors found.
         exit(0);
     } else {
         if ($this->reporter->totalFixable === 0) {
             // Errors found, but none of them can be fixed by PHPCBF.
             exit(1);
         } else {
             // Errors found, and some can be fixed by PHPCBF.
             exit(2);
         }
     }
 }