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

Source for file Reporter.php

Documentation is available at Reporter.php

  1. <?php
  2. /**
  3.  * Manages reporting of errors and warnings.
  4.  *
  5.  * @author    Greg Sherwood <gsherwood@squiz.net>
  6.  * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600)
  7.  * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
  8.  */
  9.  
  10. namespace PHP_CodeSniffer;
  11.  
  12. use PHP_CodeSniffer\Reports\Report;
  13. use PHP_CodeSniffer\Files\File;
  14. use PHP_CodeSniffer\Exceptions\RuntimeException;
  15. use PHP_CodeSniffer\Util\Common;
  16.  
  17. class Reporter
  18. {
  19.  
  20.     /**
  21.      * The config data for the run.
  22.      *
  23.      * @var \PHP_CodeSniffer\Config 
  24.      */
  25.     public $config = null;
  26.  
  27.     /**
  28.      * Total number of files that contain errors or warnings.
  29.      *
  30.      * @var integer 
  31.      */
  32.     public $totalFiles = 0;
  33.  
  34.     /**
  35.      * Total number of errors found during the run.
  36.      *
  37.      * @var integer 
  38.      */
  39.     public $totalErrors = 0;
  40.  
  41.     /**
  42.      * Total number of warnings found during the run.
  43.      *
  44.      * @var integer 
  45.      */
  46.     public $totalWarnings = 0;
  47.  
  48.     /**
  49.      * Total number of errors/warnings that can be fixed.
  50.      *
  51.      * @var integer 
  52.      */
  53.     public $totalFixable = 0;
  54.  
  55.     /**
  56.      * Total number of errors/warnings that were fixed.
  57.      *
  58.      * @var integer 
  59.      */
  60.     public $totalFixed = 0;
  61.  
  62.     /**
  63.      * When the PHPCS run started.
  64.      *
  65.      * @var float 
  66.      */
  67.     public static $startTime = 0;
  68.  
  69.     /**
  70.      * A cache of report objects.
  71.      *
  72.      * @var array 
  73.      */
  74.     private $reports = array();
  75.  
  76.     /**
  77.      * A cache of opened temporary files.
  78.      *
  79.      * @var array 
  80.      */
  81.     private $tmpFiles = array();
  82.  
  83.  
  84.     /**
  85.      * Initialise the reporter.
  86.      *
  87.      * All reports specified in the config will be created and their
  88.      * output file (or a temp file if none is specified) initialised by
  89.      * clearing the current contents.
  90.      *
  91.      * @param \PHP_CodeSniffer\Config $config The config data for the run.
  92.      *
  93.      * @return void 
  94.      * @throws RuntimeException If a report is not available.
  95.      */
  96.     public function __construct(Config $config)
  97.     {
  98.         $this->config $config;
  99.  
  100.         foreach ($config->reports as $type => $output{
  101.             $type ucfirst($type);
  102.  
  103.             if ($output === null{
  104.                 $output $config->reportFile;
  105.             }
  106.  
  107.             if (strpos($type'.'!== false{
  108.                 // This is a path to a custom report class.
  109.                 $filename realpath($type);
  110.                 if ($filename === false{
  111.                     echo "ERROR: Custom report \"$type\" not found".PHP_EOL;
  112.                     exit(3);
  113.                 }
  114.  
  115.                 $reportClassName = Autoload::loadFile($filename);
  116.             else {
  117.                 $reportClassName 'PHP_CodeSniffer\Reports\\'.$type;
  118.             }
  119.  
  120.             $reportClass = new $reportClassName();
  121.             if (false === ($reportClass instanceof Report)) {
  122.                 throw new RuntimeException('Class "'.$reportClassName.'" must implement the "PHP_CodeSniffer\Report" interface.');
  123.             }
  124.  
  125.             $this->reports[$type= array(
  126.                                      'output' => $output,
  127.                                      'class'  => $reportClass,
  128.                                     );
  129.  
  130.             if ($output === null{
  131.                 // Using a temp file.
  132.                 // This needs to be set in the constructor so that all
  133.                 // child procs use the same report file when running in parallel.
  134.                 $this->tmpFiles[$typetempnam(sys_get_temp_dir()'phpcs');
  135.                 file_put_contents($this->tmpFiles[$type]'');
  136.             else {
  137.                 file_put_contents($output'');
  138.             }
  139.         }//end foreach
  140.  
  141.     }//end __construct()
  142.  
  143.  
  144.     /**
  145.      * Generates and prints final versions of all reports.
  146.      *
  147.      * Returns TRUE if any of the reports output content to the screen
  148.      * or FALSE if all reports were silently printed to a file.
  149.      *
  150.      * @return bool 
  151.      */
  152.     public function printReports()
  153.     {
  154.         $toScreen = false;
  155.         foreach ($this->reports as $type => $report{
  156.             if ($report['output'=== null{
  157.                 $toScreen = true;
  158.             }
  159.  
  160.             $this->printReport($type);
  161.         }
  162.  
  163.         return $toScreen;
  164.  
  165.     }//end printReports()
  166.  
  167.  
  168.     /**
  169.      * Generates and prints a single final report.
  170.      *
  171.      * @param string $report The report type to print.
  172.      *
  173.      * @return void 
  174.      */
  175.     public function printReport($report)
  176.     {
  177.         $report      ucfirst($report);
  178.         $reportClass $this->reports[$report]['class'];
  179.         $reportFile  $this->reports[$report]['output'];
  180.  
  181.         if ($reportFile !== null{
  182.             $filename $reportFile;
  183.             $toScreen = false;
  184.         else {
  185.             if (isset($this->tmpFiles[$report]=== true{
  186.                 $filename $this->tmpFiles[$report];
  187.             else {
  188.                 $filename = null;
  189.             }
  190.  
  191.             $toScreen = true;
  192.         }
  193.  
  194.         $reportCache '';
  195.         if ($filename !== null{
  196.             $reportCache file_get_contents($filename);
  197.         }
  198.  
  199.         ob_start();
  200.         $reportClass->generate(
  201.             $reportCache,
  202.             $this->totalFiles,
  203.             $this->totalErrors,
  204.             $this->totalWarnings,
  205.             $this->totalFixable,
  206.             $this->config->showSources,
  207.             $this->config->reportWidth,
  208.             $this->config->interactive,
  209.             $toScreen
  210.         );
  211.         $generatedReport ob_get_contents();
  212.         ob_end_clean();
  213.  
  214.         if ($this->config->colors !== true || $reportFile !== null{
  215.             $generatedReport preg_replace('`\033\[[0-9;]+m`'''$generatedReport);
  216.         }
  217.  
  218.         if ($reportFile !== null{
  219.             if (PHP_CODESNIFFER_VERBOSITY > 0{
  220.                 echo $generatedReport;
  221.             }
  222.  
  223.             file_put_contents($reportFile$generatedReport.PHP_EOL);
  224.         else {
  225.             echo $generatedReport;
  226.             if ($filename !== null && file_exists($filename=== true{
  227.                 unlink($filename);
  228.                 unset($this->tmpFiles[$report]);
  229.             }
  230.         }
  231.  
  232.     }//end printReport()
  233.  
  234.  
  235.     /**
  236.      * Caches the result of a single processed file for all reports.
  237.      *
  238.      * The report content that is generated is appended to the output file
  239.      * assigned to each report. This content may be an intermediate report format
  240.      * and not reflect the final report output.
  241.      *
  242.      * @param \PHP_CodeSniffer\Files\File $phpcsFile The file that has been processed.
  243.      *
  244.      * @return void 
  245.      */
  246.     public function cacheFileReport(File $phpcsFile)
  247.     {
  248.         if (isset($this->config->reports=== false{
  249.             // This happens during unit testing, or any time someone just wants
  250.             // the error data and not the printed report.
  251.             return;
  252.         }
  253.  
  254.         $reportData  $this->prepareFileReport($phpcsFile);
  255.         $errorsShown = false;
  256.  
  257.         foreach ($this->reports as $type => $report{
  258.             $reportClass $report['class'];
  259.  
  260.             ob_start();
  261.             $result $reportClass->generateFileReport($reportData$phpcsFile$this->config->showSources$this->config->reportWidth);
  262.             if ($result === true{
  263.                 $errorsShown = true;
  264.             }
  265.  
  266.             $generatedReport ob_get_contents();
  267.             ob_end_clean();
  268.  
  269.             if ($report['output'=== null{
  270.                 // Using a temp file.
  271.                 if (isset($this->tmpFiles[$type]=== false{
  272.                     // When running in interactive mode, the reporter prints the full
  273.                     // report many times, which will unlink the temp file. So we need
  274.                     // to create a new one if it doesn't exist.
  275.                     $this->tmpFiles[$typetempnam(sys_get_temp_dir()'phpcs');
  276.                     file_put_contents($this->tmpFiles[$type]'');
  277.                 }
  278.  
  279.                 file_put_contents($this->tmpFiles[$type]$generatedReportFILE_APPEND);
  280.             else {
  281.                 $flags = FILE_APPEND;
  282.                 file_put_contents($report['output']$generatedReportFILE_APPEND);
  283.             }//end if
  284.         }//end foreach
  285.  
  286.         if ($errorsShown === true || PHP_CODESNIFFER_CBF === true{
  287.             $this->totalFiles++;
  288.             $this->totalErrors   += $reportData['errors'];
  289.             $this->totalWarnings += $reportData['warnings'];
  290.  
  291.             // When PHPCBF is running, we need to use the fixable error values
  292.             // after the report has run and fixed what it can.
  293.             if (PHP_CODESNIFFER_CBF === true{
  294.                 $this->totalFixable += $phpcsFile->getFixableCount();
  295.                 $this->totalFixed   += $phpcsFile->getFixedCount();
  296.             else {
  297.                 $this->totalFixable += $reportData['fixable'];
  298.             }
  299.         }
  300.  
  301.     }//end cacheFileReport()
  302.  
  303.  
  304.     /**
  305.      * Generate summary information to be used during report generation.
  306.      *
  307.      * @param \PHP_CodeSniffer\Files\File $phpcsFile The file that has been processed.
  308.      *
  309.      * @return array 
  310.      */
  311.     public function prepareFileReport(File $phpcsFile)
  312.     {
  313.         $report = array(
  314.                    'filename' => Common::stripBasepath($phpcsFile->getFilename()$this->config->basepath),
  315.                    'errors'   => $phpcsFile->getErrorCount(),
  316.                    'warnings' => $phpcsFile->getWarningCount(),
  317.                    'fixable'  => $phpcsFile->getFixableCount(),
  318.                    'messages' => array(),
  319.                   );
  320.  
  321.         if ($report['errors'=== 0 && $report['warnings'=== 0{
  322.             // Prefect score!
  323.             return $report;
  324.         }
  325.  
  326.         if ($this->config->recordErrors === false{
  327.             $message  'Errors are not being recorded but this report requires error messages. ';
  328.             $message .= 'This report will not show the correct information.';
  329.             $report['messages'][1][1= array(
  330.                                          array(
  331.                                           'message'  => $message,
  332.                                           'source'   => 'Internal.RecordErrors',
  333.                                           'severity' => 5,
  334.                                           'fixable'  => false,
  335.                                           'type'     => 'ERROR',
  336.                                          ),
  337.                                         );
  338.             return $report;
  339.         }
  340.  
  341.         $errors = array();
  342.  
  343.         // Merge errors and warnings.
  344.         foreach ($phpcsFile->getErrors(as $line => $lineErrors{
  345.             foreach ($lineErrors as $column => $colErrors{
  346.                 $newErrors = array();
  347.                 foreach ($colErrors as $data{
  348.                     $newErrors[= array(
  349.                                     'message'  => $data['message'],
  350.                                     'source'   => $data['source'],
  351.                                     'severity' => $data['severity'],
  352.                                     'fixable'  => $data['fixable'],
  353.                                     'type'     => 'ERROR',
  354.                                    );
  355.                 }
  356.  
  357.                 $errors[$line][$column$newErrors;
  358.             }
  359.  
  360.             ksort($errors[$line]);
  361.         }//end foreach
  362.  
  363.         foreach ($phpcsFile->getWarnings(as $line => $lineWarnings{
  364.             foreach ($lineWarnings as $column => $colWarnings{
  365.                 $newWarnings = array();
  366.                 foreach ($colWarnings as $data{
  367.                     $newWarnings[= array(
  368.                                       'message'  => $data['message'],
  369.                                       'source'   => $data['source'],
  370.                                       'severity' => $data['severity'],
  371.                                       'fixable'  => $data['fixable'],
  372.                                       'type'     => 'WARNING',
  373.                                      );
  374.                 }
  375.  
  376.                 if (isset($errors[$line]=== false{
  377.                     $errors[$line= array();
  378.                 }
  379.  
  380.                 if (isset($errors[$line][$column]=== true{
  381.                     $errors[$line][$columnarray_merge(
  382.                         $newWarnings,
  383.                         $errors[$line][$column]
  384.                     );
  385.                 else {
  386.                     $errors[$line][$column$newWarnings;
  387.                 }
  388.             }//end foreach
  389.  
  390.             ksort($errors[$line]);
  391.         }//end foreach
  392.  
  393.         ksort($errors);
  394.         $report['messages'$errors;
  395.         return $report;
  396.  
  397.     }//end prepareFileReport()
  398.  
  399.  
  400. }//end class

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