PHP_CodeSniffer
[ class tree: PHP_CodeSniffer ] [ index: PHP_CodeSniffer ] [ all elements ]

Source for file Runner.php

Documentation is available at Runner.php

  1. <?php
  2. /**
  3.  * Responsible for running PHPCS and PHPCBF.
  4.  *
  5.  * After creating an object of this class, you probably just want to
  6.  * call runPHPCS() or runPHPCBF().
  7.  *
  8.  * @author    Greg Sherwood <gsherwood@squiz.net>
  9.  * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600)
  10.  * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
  11.  */
  12.  
  13. namespace PHP_CodeSniffer;
  14.  
  15. use PHP_CodeSniffer\Files\FileList;
  16. use PHP_CodeSniffer\Files\File;
  17. use PHP_CodeSniffer\Files\DummyFile;
  18. use PHP_CodeSniffer\Util\Cache;
  19. use PHP_CodeSniffer\Util\Common;
  20. use PHP_CodeSniffer\Util\Standards;
  21. use PHP_CodeSniffer\Exceptions\RuntimeException;
  22.  
  23. class Runner
  24. {
  25.  
  26.     /**
  27.      * The config data for the run.
  28.      *
  29.      * @var \PHP_CodeSniffer\Config 
  30.      */
  31.     public $config = null;
  32.  
  33.     /**
  34.      * The ruleset used for the run.
  35.      *
  36.      * @var \PHP_CodeSniffer\Ruleset 
  37.      */
  38.     public $ruleset = null;
  39.  
  40.     /**
  41.      * The reporter used for generating reports after the run.
  42.      *
  43.      * @var \PHP_CodeSniffer\Reporter 
  44.      */
  45.     public $reporter = null;
  46.  
  47.  
  48.     /**
  49.      * Run the PHPCS script.
  50.      *
  51.      * @return array 
  52.      */
  53.     public function runPHPCS()
  54.     {
  55.         Util\Timing::startTiming();
  56.         Runner::checkRequirements();
  57.  
  58.         if (defined('PHP_CODESNIFFER_CBF'=== false{
  59.             define('PHP_CODESNIFFER_CBF'false);
  60.         }
  61.  
  62.         // Creating the Config object populates it with all required settings
  63.         // based on the CLI arguments provided to the script and any config
  64.         // values the user has set.
  65.         $this->config = new Config();
  66.  
  67.         // Init the run and load the rulesets to set additional config vars.
  68.         $this->init();
  69.  
  70.         // Print a list of sniffs in each of the supplied standards.
  71.         // We fudge the config here so that each standard is explained in isolation.
  72.         if ($this->config->explain === true{
  73.             $standards $this->config->standards;
  74.             foreach ($standards as $standard{
  75.                 $this->config->standards = array($standard);
  76.                 $ruleset = new Ruleset($this->config);
  77.                 $ruleset->explain();
  78.             }
  79.  
  80.             return 0;
  81.         }
  82.  
  83.         // Generate documentation for each of the supplied standards.
  84.         if ($this->config->generator !== null{
  85.             $standards $this->config->standards;
  86.             foreach ($standards as $standard{
  87.                 $this->config->standards = array($standard);
  88.                 $ruleset   = new Ruleset($this->config);
  89.                 $class     'PHP_CodeSniffer\Generators\\'.$this->config->generator;
  90.                 $generator = new $class($ruleset);
  91.                 $generator->generate();
  92.             }
  93.  
  94.             return 0;
  95.         }
  96.  
  97.         // Other report formats don't really make sense in interactive mode
  98.         // so we hard-code the full report here and when outputting.
  99.         // We also ensure parallel processing is off because we need to do one file at a time.
  100.         if ($this->config->interactive === true{
  101.             $this->config->reports      = array('full' => null);
  102.             $this->config->parallel     = 1;
  103.             $this->config->showProgress = false;
  104.         }
  105.  
  106.         // Disable caching if we are processing STDIN as we can't be 100%
  107.         // sure where the file came from or if it will change in the future.
  108.         if ($this->config->stdin === true{
  109.             $this->config->cache = false;
  110.         }
  111.  
  112.         $numErrors $this->run();
  113.  
  114.         // Print all the reports for this run.
  115.         $toScreen $this->reporter->printReports();
  116.  
  117.         // Only print timer output if no reports were
  118.         // printed to the screen so we don't put additional output
  119.         // in something like an XML report. If we are printing to screen,
  120.         // the report types would have already worked out who should
  121.         // print the timer info.
  122.         if ($this->config->interactive === false
  123.             && ($toScreen === false
  124.             || (($this->reporter->totalErrors + $this->reporter->totalWarnings=== 0 && $this->config->showProgress === true))
  125.         {
  126.             Util\Timing::printRunTime();
  127.         }
  128.  
  129.         if ($numErrors === 0{
  130.             // No errors found.
  131.             return 0;
  132.         else if ($this->reporter->totalFixable === 0{
  133.             // Errors found, but none of them can be fixed by PHPCBF.
  134.             return 1;
  135.         else {
  136.             // Errors found, and some can be fixed by PHPCBF.
  137.             return 2;
  138.         }
  139.  
  140.     }//end runPHPCS()
  141.  
  142.  
  143.     /**
  144.      * Run the PHPCBF script.
  145.      *
  146.      * @return array 
  147.      */
  148.     public function runPHPCBF()
  149.     {
  150.         if (defined('PHP_CODESNIFFER_CBF'=== false{
  151.             define('PHP_CODESNIFFER_CBF'true);
  152.         }
  153.  
  154.         Util\Timing::startTiming();
  155.         Runner::checkRequirements();
  156.  
  157.         // Creating the Config object populates it with all required settings
  158.         // based on the CLI arguments provided to the script and any config
  159.         // values the user has set.
  160.         $this->config = new Config();
  161.  
  162.         // When processing STDIN, we can't output anything to the screen
  163.         // or it will end up mixed in with the file output.
  164.         if ($this->config->stdin === true{
  165.             $this->config->verbosity = 0;
  166.         }
  167.  
  168.         // Init the run and load the rulesets to set additional config vars.
  169.         $this->init();
  170.  
  171.         // Override some of the command line settings that might break the fixes.
  172.         $this->config->generator    = null;
  173.         $this->config->explain      = false;
  174.         $this->config->interactive  = false;
  175.         $this->config->cache        = false;
  176.         $this->config->showSources  = false;
  177.         $this->config->recordErrors = false;
  178.         $this->config->reportFile   = null;
  179.         $this->config->reports      = array('cbf' => null);
  180.  
  181.         // If a standard tries to set command line arguments itself, some
  182.         // may be blocked because PHPCBF is running, so stop the script
  183.         // dying if any are found.
  184.         $this->config->dieOnUnknownArg = false;
  185.  
  186.         $numErrors $this->run();
  187.         $this->reporter->printReports();
  188.  
  189.         echo PHP_EOL;
  190.         Util\Timing::printRunTime();
  191.  
  192.         if ($this->reporter->totalFixed === 0{
  193.             // Nothing was fixed by PHPCBF.
  194.             if ($this->reporter->totalFixable === 0{
  195.                 // Nothing found that could be fixed.
  196.                 return 0;
  197.             else {
  198.                 // Something failed to fix.
  199.                 return 2;
  200.             }
  201.         }
  202.  
  203.         if ($this->reporter->totalFixable === 0{
  204.             // PHPCBF fixed all fixable errors.
  205.             return 1;
  206.         }
  207.  
  208.         // PHPCBF fixed some fixable errors, but others failed to fix.
  209.         return 2;
  210.  
  211.     }//end runPHPCBF()
  212.  
  213.  
  214.     /**
  215.      * Exits if the minimum requirements of PHP_CodSniffer are not met.
  216.      *
  217.      * @return array 
  218.      */
  219.     public function checkRequirements()
  220.     {
  221.         // Check the PHP version.
  222.         if (PHP_VERSION_ID < 50400{
  223.             echo 'ERROR: PHP_CodeSniffer requires PHP version 5.4.0 or greater.'.PHP_EOL;
  224.             exit(3);
  225.         }
  226.  
  227.         if (extension_loaded('tokenizer'=== false{
  228.             echo 'ERROR: PHP_CodeSniffer requires the tokenizer extension to be enabled.'.PHP_EOL;
  229.             exit(3);
  230.         }
  231.  
  232.     }//end checkRequirements()
  233.  
  234.  
  235.     /**
  236.      * Init the rulesets and other high-level settings.
  237.      *
  238.      * @return void 
  239.      */
  240.     public function init()
  241.     {
  242.         if (defined('PHP_CODESNIFFER_CBF'=== false{
  243.             define('PHP_CODESNIFFER_CBF'false);
  244.         }
  245.  
  246.         // Ensure this option is enabled or else line endings will not always
  247.         // be detected properly for files created on a Mac with the /r line ending.
  248.         ini_set('auto_detect_line_endings'true);
  249.  
  250.         // Check that the standards are valid.
  251.         foreach ($this->config->standards as $standard{
  252.             if (Util\Standards::isInstalledStandard($standard=== false{
  253.                 // They didn't select a valid coding standard, so help them
  254.                 // out by letting them know which standards are installed.
  255.                 echo 'ERROR: the "'.$standard.'" coding standard is not installed. ';
  256.                 Util\Standards::printInstalledStandards();
  257.                 exit(3);
  258.             }
  259.         }
  260.  
  261.         // Saves passing the Config object into other objects that only need
  262.         // the verbostity flag for deubg output.
  263.         if (defined('PHP_CODESNIFFER_VERBOSITY'=== false{
  264.             define('PHP_CODESNIFFER_VERBOSITY'$this->config->verbosity);
  265.         }
  266.  
  267.         // Create this class so it is autoloaded and sets up a bunch
  268.         // of PHP_CodeSniffer-specific token type constants.
  269.         $tokens = new Util\Tokens();
  270.  
  271.         // Allow autoloading of custom files inside installed standards.
  272.         $installedStandards = Standards::getInstalledStandardDetails();
  273.         foreach ($installedStandards as $name => $details{
  274.             Autoload::addSearchPath($details['path']$details['namespace']);
  275.         }
  276.  
  277.         // The ruleset contains all the information about how the files
  278.         // should be checked and/or fixed.
  279.         try {
  280.             $this->ruleset = new Ruleset($this->config);
  281.         catch (RuntimeException $e{
  282.             echo 'ERROR: '.$e->getMessage().PHP_EOL.PHP_EOL;
  283.             $this->config->printShortUsage();
  284.             exit(3);
  285.         }
  286.  
  287.     }//end init()
  288.  
  289.  
  290.     /**
  291.      * Performs the run.
  292.      *
  293.      * @return int The number of errors and warnings found.
  294.      */
  295.     private function run()
  296.     {
  297.         // The class that manages all reporters for the run.
  298.         $this->reporter = new Reporter($this->config);
  299.  
  300.         // Include bootstrap files.
  301.         foreach ($this->config->bootstrap as $bootstrap{
  302.             include $bootstrap;
  303.         }
  304.  
  305.         if ($this->config->stdin === true{
  306.             $fileContents $this->config->stdinContent;
  307.             if ($fileContents === null{
  308.                 $handle fopen('php://stdin''r');
  309.                 stream_set_blocking($handletrue);
  310.                 $fileContents stream_get_contents($handle);
  311.                 fclose($handle);
  312.             }
  313.  
  314.             $todo  = new FileList($this->config$this->ruleset);
  315.             $dummy = new DummyFile($fileContents$this->ruleset$this->config);
  316.             $todo->addFile($dummy->path$dummy);
  317.         else {
  318.             if (empty($this->config->files=== true{
  319.                 echo 'ERROR: You must supply at least one file or directory to process.'.PHP_EOL.PHP_EOL;
  320.                 $this->config->printUsage();
  321.                 exit(0);
  322.             }
  323.  
  324.             if (PHP_CODESNIFFER_VERBOSITY > 0{
  325.                 echo 'Creating file list... ';
  326.             }
  327.  
  328.             $todo = new FileList($this->config$this->ruleset);
  329.  
  330.             if (PHP_CODESNIFFER_VERBOSITY > 0{
  331.                 $numFiles count($todo);
  332.                 echo "DONE ($numFiles files in queue)".PHP_EOL;
  333.             }
  334.  
  335.             if ($this->config->cache === true{
  336.                 if (PHP_CODESNIFFER_VERBOSITY > 0{
  337.                     echo 'Loading cache... ';
  338.                 }
  339.  
  340.                 Cache::load($this->ruleset$this->config);
  341.  
  342.                 if (PHP_CODESNIFFER_VERBOSITY > 0{
  343.                     $size = Cache::getSize();
  344.                     echo "DONE ($size files in cache)".PHP_EOL;
  345.                 }
  346.             }
  347.         }//end if
  348.  
  349.         // Turn all sniff errors into exceptions.
  350.         set_error_handler(array($this'handleErrors'));
  351.  
  352.         // If verbosity is too high, turn off parallelism so the
  353.         // debug output is clean.
  354.         if (PHP_CODESNIFFER_VERBOSITY > 1{
  355.             $this->config->parallel = 1;
  356.         }
  357.  
  358.         // If the PCNTL extension isn't installed, we can't fork.
  359.         if (function_exists('pcntl_fork'=== false{
  360.             $this->config->parallel = 1;
  361.         }
  362.  
  363.         $lastDir  '';
  364.         $numFiles count($todo);
  365.  
  366.         if ($this->config->parallel === 1{
  367.             // Running normally.
  368.             $numProcessed = 0;
  369.             foreach ($todo as $path => $file{
  370.                 if ($file->ignored === true{
  371.                     continue;
  372.                 }
  373.  
  374.                 $currDir dirname($path);
  375.                 if ($lastDir !== $currDir{
  376.                     if (PHP_CODESNIFFER_VERBOSITY > 0{
  377.                         echo 'Changing into directory '.Common::stripBasepath($currDir$this->config->basepath).PHP_EOL;
  378.                     }
  379.  
  380.                     $lastDir $currDir;
  381.                 }
  382.  
  383.                 $this->processFile($file);
  384.  
  385.                 $numProcessed++;
  386.                 $this->printProgress($file$numFiles$numProcessed);
  387.             }
  388.         else {
  389.             // Batching and forking.
  390.             $childProcs  = array();
  391.             $numPerBatch ceil($numFiles $this->config->parallel);
  392.  
  393.             for ($batch = 0; $batch $this->config->parallel; $batch++{
  394.                 $startAt ($batch $numPerBatch);
  395.                 if ($startAt >= $numFiles{
  396.                     break;
  397.                 }
  398.  
  399.                 $endAt ($startAt $numPerBatch);
  400.                 if ($endAt $numFiles{
  401.                     $endAt $numFiles;
  402.                 }
  403.  
  404.                 $childOutFilename tempnam(sys_get_temp_dir()'phpcs-child');
  405.                 $pid pcntl_fork();
  406.                 if ($pid === -1{
  407.                     throw new RuntimeException('Failed to create child process');
  408.                 else if ($pid !== 0{
  409.                     $childProcs[= array(
  410.                                      'pid' => $pid,
  411.                                      'out' => $childOutFilename,
  412.                                     );
  413.                 else {
  414.                     // Move forward to the start of the batch.
  415.                     $todo->rewind();
  416.                     for ($i = 0; $i $startAt$i++{
  417.                         $todo->next();
  418.                     }
  419.  
  420.                     // Reset the reporter to make sure only figures from this
  421.                     // file batch are recorded.
  422.                     $this->reporter->totalFiles    = 0;
  423.                     $this->reporter->totalErrors   = 0;
  424.                     $this->reporter->totalWarnings = 0;
  425.                     $this->reporter->totalFixable  = 0;
  426.                     $this->reporter->totalFixed    = 0;
  427.  
  428.                     // Process the files.
  429.                     $pathsProcessed = array();
  430.                     ob_start();
  431.                     for ($i $startAt$i $endAt$i++{
  432.                         $path $todo->key();
  433.                         $file $todo->current();
  434.  
  435.                         if ($file->ignored === true{
  436.                             continue;
  437.                         }
  438.  
  439.                         $currDir dirname($path);
  440.                         if ($lastDir !== $currDir{
  441.                             if (PHP_CODESNIFFER_VERBOSITY > 0{
  442.                                 echo 'Changing into directory '.Common::stripBasepath($currDir$this->config->basepath).PHP_EOL;
  443.                             }
  444.  
  445.                             $lastDir $currDir;
  446.                         }
  447.  
  448.                         $this->processFile($file);
  449.  
  450.                         $pathsProcessed[$path;
  451.                         $todo->next();
  452.                     }//end for
  453.  
  454.                     $debugOutput ob_get_contents();
  455.                     ob_end_clean();
  456.  
  457.                     // Write information about the run to the filesystem
  458.                     // so it can be picked up by the main process.
  459.                     $childOutput = array(
  460.                                     'totalFiles'    => $this->reporter->totalFiles,
  461.                                     'totalErrors'   => $this->reporter->totalErrors,
  462.                                     'totalWarnings' => $this->reporter->totalWarnings,
  463.                                     'totalFixable'  => $this->reporter->totalFixable,
  464.                                     'totalFixed'    => $this->reporter->totalFixed,
  465.                                    );
  466.  
  467.                     $output  '<'.'?php'."\n".' $childOutput = ';
  468.                     $output .= var_export($childOutputtrue);
  469.                     $output .= ";\n\$debugOutput = ";
  470.                     $output .= var_export($debugOutputtrue);
  471.  
  472.                     if ($this->config->cache === true{
  473.                         $childCache = array();
  474.                         foreach ($pathsProcessed as $path{
  475.                             $childCache[$path= Cache::get($path);
  476.                         }
  477.  
  478.                         $output .= ";\n\$childCache = ";
  479.                         $output .= var_export($childCachetrue);
  480.                     }
  481.  
  482.                     $output .= ";\n?".'>';
  483.                     file_put_contents($childOutFilename$output);
  484.                     exit($pid);
  485.                 }//end if
  486.             }//end for
  487.  
  488.             $this->processChildProcs($childProcs);
  489.         }//end if
  490.  
  491.         restore_error_handler();
  492.  
  493.         if (PHP_CODESNIFFER_VERBOSITY === 0
  494.             && $this->config->interactive === false
  495.             && $this->config->showProgress === true
  496.         {
  497.             echo PHP_EOL.PHP_EOL;
  498.         }
  499.  
  500.         if ($this->config->cache === true{
  501.             Cache::save();
  502.         }
  503.  
  504.         $ignoreWarnings = Config::getConfigData('ignore_warnings_on_exit');
  505.         $ignoreErrors   = Config::getConfigData('ignore_errors_on_exit');
  506.  
  507.         $return ($this->reporter->totalErrors + $this->reporter->totalWarnings);
  508.         if ($ignoreErrors !== null{
  509.             $ignoreErrors = (bool) $ignoreErrors;
  510.             if ($ignoreErrors === true{
  511.                 $return -= $this->reporter->totalErrors;
  512.             }
  513.         }
  514.  
  515.         if ($ignoreWarnings !== null{
  516.             $ignoreWarnings = (bool) $ignoreWarnings;
  517.             if ($ignoreWarnings === true{
  518.                 $return -= $this->reporter->totalWarnings;
  519.             }
  520.         }
  521.  
  522.         return $return;
  523.  
  524.     }//end run()
  525.  
  526.  
  527.     /**
  528.      * Converts all PHP errors into exceptions.
  529.      *
  530.      * This method forces a sniff to stop processing if it is not
  531.      * able to handle a specific piece of code, instead of continuing
  532.      * and potentially getting into a loop.
  533.      *
  534.      * @param int    $code    The level of error raised.
  535.      * @param string $message The error message.
  536.      * @param string $file    The path of the file that raised the error.
  537.      * @param int    $line    The line number the error was raised at.
  538.      *
  539.      * @return void 
  540.      */
  541.     public function handleErrors($code$message$file$line)
  542.     {
  543.         throw new RuntimeException("$message in $file on line $line");
  544.  
  545.     }//end handleErrors()
  546.  
  547.  
  548.     /**
  549.      * Processes a single file, including checking and fixing.
  550.      *
  551.      * @param \PHP_CodeSniffer\Files\File $file The file to be processed.
  552.      *
  553.      * @return void 
  554.      */
  555.     public function processFile($file)
  556.     {
  557.         if (PHP_CODESNIFFER_VERBOSITY > 0{
  558.             $startTime microtime(true);
  559.             echo 'Processing '.basename($file->path).' ';
  560.             if (PHP_CODESNIFFER_VERBOSITY > 1{
  561.                 echo PHP_EOL;
  562.             }
  563.         }
  564.  
  565.         try {
  566.             $file->process();
  567.  
  568.             if (PHP_CODESNIFFER_VERBOSITY > 0{
  569.                 $timeTaken ((microtime(true$startTime* 1000);
  570.                 if ($timeTaken < 1000{
  571.                     $timeTaken round($timeTaken);
  572.                     echo "DONE in {$timeTaken}ms";
  573.                 else {
  574.                     $timeTaken round(($timeTaken / 1000)2);
  575.                     echo "DONE in $timeTaken secs";
  576.                 }
  577.  
  578.                 if (PHP_CODESNIFFER_CBF === true{
  579.                     $errors $file->getFixableCount();
  580.                     echo " ($errors fixable violations)".PHP_EOL;
  581.                 else {
  582.                     $errors   $file->getErrorCount();
  583.                     $warnings $file->getWarningCount();
  584.                     echo " ($errors errors, $warnings warnings)".PHP_EOL;
  585.                 }
  586.             }
  587.         catch (\Exception $e{
  588.             $error 'An error occurred during processing; checking has been aborted. The error message was: '.$e->getMessage();
  589.             $file->addErrorOnLine($error1'Internal.Exception');
  590.         }//end try
  591.  
  592.         $this->reporter->cacheFileReport($file$this->config);
  593.  
  594.         if ($this->config->interactive === true{
  595.             /*
  596.                 Running interactively.
  597.                 Print the error report for the current file and then wait for user input.
  598.             */
  599.  
  600.             // Get current violations and then clear the list to make sure
  601.             // we only print violations for a single file each time.
  602.             $numErrors = null;
  603.             while ($numErrors !== 0{
  604.                 $numErrors ($file->getErrorCount($file->getWarningCount());
  605.                 if ($numErrors === 0{
  606.                     continue;
  607.                 }
  608.  
  609.                 $this->reporter->printReport('full');
  610.  
  611.                 echo '<ENTER> to recheck, [s] to skip or [q] to quit : ';
  612.                 $input fgets(STDIN);
  613.                 $input trim($input);
  614.  
  615.                 switch ($input{
  616.                 case 's':
  617.                     break(2);
  618.                 case 'q':
  619.                     exit(0);
  620.                 default:
  621.                     // Repopulate the sniffs because some of them save their state
  622.                     // and only clear it when the file changes, but we are rechecking
  623.                     // the same file.
  624.                     $file->ruleset->populateTokenListeners();
  625.                     $file->reloadContent();
  626.                     $file->process();
  627.                     $this->reporter->cacheFileReport($file$this->config);
  628.                     break;
  629.                 }
  630.             }//end while
  631.         }//end if
  632.  
  633.         // Clean up the file to save (a lot of) memory.
  634.         $file->cleanUp();
  635.  
  636.     }//end processFile()
  637.  
  638.  
  639.     /**
  640.      * Waits for child processes to complete and cleans up after them.
  641.      *
  642.      * The reporting information returned by each child process is merged
  643.      * into the main reporter class.
  644.      *
  645.      * @param array $childProcs An array of child processes to wait for.
  646.      *
  647.      * @return void 
  648.      */
  649.     private function processChildProcs($childProcs)
  650.     {
  651.         $numProcessed = 0;
  652.         $totalBatches count($childProcs);
  653.  
  654.         while (count($childProcs> 0{
  655.             foreach ($childProcs as $key => $procData{
  656.                 $res pcntl_waitpid($procData['pid']$statusWNOHANG);
  657.                 if ($res === $procData['pid']{
  658.                     if (file_exists($procData['out']=== true{
  659.                         include $procData['out'];
  660.                         if (isset($childOutput=== true{
  661.                             $this->reporter->totalFiles    += $childOutput['totalFiles'];
  662.                             $this->reporter->totalErrors   += $childOutput['totalErrors'];
  663.                             $this->reporter->totalWarnings += $childOutput['totalWarnings'];
  664.                             $this->reporter->totalFixable  += $childOutput['totalFixable'];
  665.                             $this->reporter->totalFixed    += $childOutput['totalFixed'];
  666.                         }
  667.  
  668.                         if (isset($debugOutput=== true{
  669.                             echo $debugOutput;
  670.                         }
  671.  
  672.                         if (isset($childCache=== true{
  673.                             foreach ($childCache as $path => $cache{
  674.                                 Cache::set($path$cache);
  675.                             }
  676.                         }
  677.  
  678.                         unlink($procData['out']);
  679.                         unset($childProcs[$key]);
  680.  
  681.                         $numProcessed++;
  682.  
  683.                         // Fake a processed file so we can print progress output for the batch.
  684.                         $file = new DummyFile(null$this->ruleset$this->config);
  685.                         $file->setErrorCounts(
  686.                             $childOutput['totalErrors'],
  687.                             $childOutput['totalWarnings'],
  688.                             $childOutput['totalFixable'],
  689.                             $childOutput['totalFixed']
  690.                         );
  691.                         $this->printProgress($file$totalBatches$numProcessed);
  692.                     }//end if
  693.                 }//end if
  694.             }//end foreach
  695.         }//end while
  696.  
  697.     }//end processChildProcs()
  698.  
  699.  
  700.     /**
  701.      * Print progress information for a single processed file.
  702.      *
  703.      * @param File $file         The file that was processed.
  704.      * @param int  $numFiles     The total number of files to process.
  705.      * @param int  $numProcessed The number of files that have been processed,
  706.      *                            including this one.
  707.      *
  708.      * @return void 
  709.      */
  710.     function printProgress($file$numFiles$numProcessed)
  711.     {
  712.         if (PHP_CODESNIFFER_VERBOSITY > 0
  713.             || $this->config->showProgress === false
  714.         {
  715.             return;
  716.         }
  717.  
  718.         // Show progress information.
  719.         if ($file->ignored === true{
  720.             echo 'S';
  721.         else {
  722.             $errors   $file->getErrorCount();
  723.             $warnings $file->getWarningCount();
  724.             $fixable  $file->getFixableCount();
  725.             $fixed    $file->getFixedCount();
  726.  
  727.             if (PHP_CODESNIFFER_CBF === true{
  728.                 // Files with fixed errors or warnings are F (green).
  729.                 // Files with unfixable errors or warnings are E (red).
  730.                 // Files with no errors or warnings are . (black).
  731.                 if ($fixable > 0{
  732.                     if ($this->config->colors === true{
  733.                         echo "\033[31m";
  734.                     }
  735.  
  736.                     echo 'E';
  737.  
  738.                     if ($this->config->colors === true{
  739.                         echo "\033[0m";
  740.                     }
  741.                 else if ($fixed > 0{
  742.                     if ($this->config->colors === true{
  743.                         echo "\033[32m";
  744.                     }
  745.  
  746.                     echo 'F';
  747.  
  748.                     if ($this->config->colors === true{
  749.                         echo "\033[0m";
  750.                     }
  751.                 else {
  752.                     echo '.';
  753.                 }//end if
  754.             else {
  755.                 // Files with errors are E (red).
  756.                 // Files with fixable errors are E (green).
  757.                 // Files with warnings are W (yellow).
  758.                 // Files with fixable warnings are W (green).
  759.                 // Files with no errors or warnings are . (black).
  760.                 if ($errors > 0{
  761.                     if ($this->config->colors === true{
  762.                         if ($fixable > 0{
  763.                             echo "\033[32m";
  764.                         else {
  765.                             echo "\033[31m";
  766.                         }
  767.                     }
  768.  
  769.                     echo 'E';
  770.  
  771.                     if ($this->config->colors === true{
  772.                         echo "\033[0m";
  773.                     }
  774.                 else if ($warnings > 0{
  775.                     if ($this->config->colors === true{
  776.                         if ($fixable > 0{
  777.                             echo "\033[32m";
  778.                         else {
  779.                             echo "\033[33m";
  780.                         }
  781.                     }
  782.  
  783.                     echo 'W';
  784.  
  785.                     if ($this->config->colors === true{
  786.                         echo "\033[0m";
  787.                     }
  788.                 else {
  789.                     echo '.';
  790.                 }//end if
  791.             }//end if
  792.         }//end if
  793.  
  794.         if (($numProcessed % 60=== 0{
  795.             $padding (strlen($numFilesstrlen($numProcessed));
  796.             echo str_repeat(' '$padding);
  797.             $percent round(($numProcessed $numFiles* 100);
  798.             echo " $numProcessed / $numFiles ($percent%)".PHP_EOL;
  799.         }
  800.  
  801.     }//end printProgress()
  802.  
  803.  
  804. }//end class

Documentation generated on Mon, 11 Mar 2019 14:18:11 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.