Skip to content

Commit 773b940

Browse files
stronk7vmdef
authored andcommitted
Create our own runner/report and use it from the UI
Using the bundled runner from UI requires some nasty hacks (faking argv...) and it supports a lot of features we aren't interested. So, instead, just create our own runner (extending upstream one) with custom init and run methods, and that all. Moved as much as possible from locallib to classes. Modify index.php to work with the new runner. Also, some small code/phpdoc style fixes.
1 parent 95fc65d commit 773b940

File tree

4 files changed

+258
-123
lines changed

4 files changed

+258
-123
lines changed

classes/report.php

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
<?php
2+
// This file is part of Moodle - http://moodle.org/
3+
//
4+
// Moodle is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// Moodle is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU General Public License
15+
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
16+
17+
/**
18+
* Custom PHP_CodeSniffer XML Report for local_codechecker.
19+
*
20+
* @package local_codechecker
21+
* @copyright 2020 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com}
22+
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23+
*/
24+
25+
namespace local_codechecker;
26+
27+
// phpcs:disable moodle.NamingConventions
28+
29+
/**
30+
* Custom PHP_CodeSniffer XML Report for local_codechecker.
31+
*
32+
* This custom report is exactly the upstream XML one, but
33+
* with a few modifications when there aren't errors and warnings.
34+
*
35+
* @copyright 2020 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com}
36+
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
37+
*/
38+
class report extends \PHP_CodeSniffer\Reports\Xml {
39+
40+
/**
41+
* Generate a partial report for a single processed file.
42+
*
43+
* For files with violations delegate processing to parent class. For files
44+
* without violations, just return the plain <file> element, without any err/warn.
45+
*
46+
* @param array $report Prepared report data.
47+
* @param \PHP_CodeSniffer\Files\File $phpcsFile The file being reported on.
48+
* @param boolean $showSources Show sources?
49+
* @param int $width Maximum allowed line width.
50+
*
51+
* @return boolean
52+
*/
53+
public function generateFileReport($report, \PHP_CodeSniffer\Files\File $phpcsFile, $showSources = false, $width = 80) {
54+
55+
// Report has violations, delegate to parent standard processing.
56+
if ($report['errors'] !== 0 || $report['warnings'] !== 0) {
57+
return parent::generateFileReport($report, $phpcsFile, $showSources, $width);
58+
}
59+
60+
// Here we are, with a file with 0 errors and warnings.
61+
$out = new \XMLWriter;
62+
$out->openMemory();
63+
$out->setIndent(true);
64+
65+
$out->startElement('file');
66+
$out->writeAttribute('name', $report['filename']);
67+
$out->writeAttribute('errors', $report['errors']);
68+
$out->writeAttribute('warnings', $report['warnings']);
69+
70+
$out->endElement();
71+
echo $out->flush();
72+
73+
return true;
74+
75+
}
76+
}

classes/runner.php

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
<?php
2+
// This file is part of Moodle - http://moodle.org/
3+
//
4+
// Moodle is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// Moodle is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU General Public License
15+
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
16+
17+
/**
18+
* Custom PHP_CodeSniffer Runner for local_codechecker.
19+
*
20+
* @package local_codechecker
21+
* @copyright 2020 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com}
22+
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23+
*/
24+
25+
namespace local_codechecker;
26+
27+
/**
28+
* Custom PHP_CodeSniffer\Runner for local_codechecker.
29+
*
30+
* This custom runner just intercepts the init() method, to be able
31+
* to add all our configuration. The alternative to this is to play
32+
* with fake $_SERVER['argv' {@see PHP_CodeSniffer\Config}.
33+
*
34+
* @copyright 2020 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com}
35+
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
36+
*/
37+
class runner extends \PHP_CodeSniffer\Runner {
38+
39+
/**
40+
* Create an instance of the runner.
41+
*/
42+
public function __construct() {
43+
// Needed constant.
44+
if (defined('PHP_CODESNIFFER_CBF') === false) {
45+
define('PHP_CODESNIFFER_CBF', true);
46+
}
47+
// Pass the parallel as CLI, disabled. Note
48+
// this is to avoid some nasty argv notices.
49+
$this->config = new \PHP_CodeSniffer\Config([
50+
'--parallel=1',
51+
]);
52+
}
53+
54+
/**
55+
* Set the file where the XML report is going to be written
56+
*
57+
* @param string $reportfile file path to XML report.
58+
*/
59+
public function set_reportfile($reportfile) {
60+
$this->config->reports = [report::class => $reportfile];
61+
}
62+
63+
/**
64+
* Set if the report should include warnings or no.
65+
*
66+
* @param bool $includewarnings
67+
*/
68+
public function set_includewarnings($includewarnings) {
69+
if (empty($includewarnings)) {
70+
$this->config->warningSeverity = 0; // Disable warnings.
71+
}
72+
}
73+
74+
/**
75+
* Set the files the runned is going to process.
76+
*
77+
* @param string[] $files array of full paths to files or directories.
78+
*/
79+
public function set_files($files) {
80+
$this->config->files = $files;
81+
}
82+
83+
/**
84+
* Set all the patterns in file paths to be ignored
85+
*
86+
* @param string[] $ignorepatterns array of paths to ignore (libs, fixtures...)
87+
*/
88+
public function set_ignorepatterns($ignorepatterns) {
89+
$this->config->ignored = $ignorepatterns;
90+
}
91+
92+
/**
93+
* Initialise the runner, invoked by run().
94+
*/
95+
public function init() {
96+
97+
$this->config->standards = ['moodle'];
98+
$this->config->extensions = ['php' => 'PHP'];
99+
100+
// Added all our customizations, finally call parent.
101+
parent::init();
102+
}
103+
104+
/**
105+
* Runs a codechecker execution.
106+
*
107+
* Instead of using the upstream runner, we just use this reduced version
108+
* that simplifies all the configuration, init and processing to suit
109+
* codechecker simpler needs from the UI.
110+
*/
111+
public function run() {
112+
// Setup everything.
113+
$this->init();
114+
115+
// Create the reporter to manage all the reports from the run.
116+
$reporter = new \PHP_CodeSniffer\Reporter($this->config);
117+
118+
// And build the file list to iterate over.
119+
$todo = new \PHP_CodeSniffer\Files\FileList($this->config, $this->ruleset);
120+
121+
foreach ($todo as $file) {
122+
if ($file->ignored === false) {
123+
try {
124+
$file->process();
125+
} catch (\Exception $e) {
126+
$error = 'Problem during processing; checking has been aborted. The error message was: '.$e->getMessage();
127+
$file->addErrorOnLine($error, 1, 'Internal.Exception');
128+
}
129+
// Add results to the reporter and free memory.
130+
$reporter->cacheFileReport($file, $this->config);
131+
$file->cleanUp();
132+
}
133+
}
134+
135+
// Have finished, generate the final reports.
136+
$reporter->printReports();
137+
}
138+
}

index.php

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,17 @@
2424

2525
require_once(__DIR__ . '/../../config.php');
2626
require_once($CFG->libdir . '/adminlib.php');
27+
28+
// PHP_Codesniffer autoloading.
29+
if (is_file(__DIR__ . '/phpcs/autoload.php') === true) {
30+
include_once(__DIR__ . '/phpcs/autoload.php');
31+
} else {
32+
include_once('PHP/CodeSniffer/autoload.php');
33+
}
34+
// PHPCompatibility autoloading.
35+
require_once('PHPCSAliases.php');
36+
37+
// Own stuff (TODO: Some day all these will be moved to classes).
2738
require_once($CFG->dirroot . '/local/codechecker/locallib.php');
2839

2940
$pathlist = optional_param('path', '', PARAM_RAW);
@@ -75,19 +86,21 @@
7586
}
7687

7788
if ($fullpaths && !$failed) {
89+
// Let's use our own Runner, all we need is to pass some
90+
// configuration settings (reportfile, show warnings) and
91+
// override the init() method to set all our config options.
92+
// Finally, use own run() method, much simplified from
93+
// the runPHPCS() upstream one.
94+
$runner = new \local_codechecker\runner();
95+
7896
$reportfile = make_temp_directory('phpcs') . '/phpcs_' . random_string(10) . '.xml';
79-
$phpcs = new PHP_CodeSniffer();
80-
$phpcs->setAllowedFileExtensions(['php']); // We are only going to process php files ever.
81-
$cli = new local_codechecker_codesniffer_cli();
82-
$cli->setReport('local_codechecker'); // Using own custom xml format for easier handling later.
83-
$cli->setReportFile($reportfile); // Send the report to dataroot temp.
84-
$cli->setIncludeWarnings($includewarnings); // Decide if we want to show warnings (defaults yes).
85-
$phpcs->setCli($cli);
86-
$phpcs->setIgnorePatterns(local_codesniffer_get_ignores($exclude));
87-
$phpcs->process($fullpaths,
88-
local_codechecker_clean_path($CFG->dirroot . '/local/codechecker/moodle'));
89-
// Save the xml report file to dataroot/temp.
90-
$phpcs->reporting->printReport('local_codechecker', false, $cli->getCommandLineValues(), $reportfile);
97+
$runner->set_reportfile($reportfile);
98+
$runner->set_includewarnings($includewarnings);
99+
$runner->set_ignorepatterns(local_codesniffer_get_ignores($exclude));
100+
$runner->set_files($fullpaths);
101+
102+
$runner->run();
103+
91104
// Load the XML file to proceed with the rest of checks.
92105
$xml = simplexml_load_file($reportfile);
93106

0 commit comments

Comments
 (0)