SARIFRenderer::addViolationsToReport()   B
last analyzed

Complexity

Conditions 6
Paths 11

Size

Total Lines 82
Code Lines 52

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 43
CRAP Score 6

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 6
eloc 52
nc 11
nop 2
dl 0
loc 82
ccs 43
cts 43
cp 1
crap 6
rs 8.425
c 1
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * This file is part of PHP Mess Detector.
4
 *
5
 * Copyright (c) Manuel Pichler <[email protected]>.
6
 * All rights reserved.
7
 *
8
 * Licensed under BSD License
9
 * For full copyright and license information, please see the LICENSE file.
10
 * Redistributions of files must retain the above copyright notice.
11
 *
12
 * @author Lukas Bestle <[email protected]>
13
 * @copyright Manuel Pichler. All rights reserved.
14
 * @license https://opensource.org/licenses/bsd-license.php BSD License
15
 * @link http://phpmd.org/
16
 */
17
18
namespace PHPMD\Renderer;
19
20
use PHPMD\PHPMD;
21
use PHPMD\Report;
22
use PHPMD\Renderer\JSONRenderer;
23
24
/**
25
 * This class will render a SARIF (Static Analysis
26
 * Results Interchange Format) report.
27
 */
28
class SARIFRenderer extends JSONRenderer
29
{
30
    /**
31
     * Create report data and add renderer meta properties
32
     *
33
     * @return array
34
     */
35 2
    protected function initReportData()
36
    {
37 2
        $data = array(
38 2
            'version' => '2.1.0',
39
            '$schema' =>
40
                'https://raw.githubusercontent.com/oasis-tcs/' .
41 2
                'sarif-spec/master/Schemata/sarif-schema-2.1.0.json',
42
            'runs' => array(
43
                array(
44
                    'tool' => array(
45
                        'driver' => array(
46
                            'name' => 'PHPMD',
47
                            'informationUri' => 'https://phpmd.org',
48
                            'version' => PHPMD::VERSION,
49
                            'rules' => array(),
50
                        ),
51
                    ),
52
                    'originalUriBaseIds' => array(
53
                        'WORKINGDIR' => array(
54 2
                            'uri' => static::pathToUri(getcwd()) . '/',
55
                        ),
56
                    ),
57
                    'results' => array(),
58
                ),
59
            ),
60
        );
61
62 2
        return $data;
63
    }
64
65
    /**
66
     * Add violations, if any, to the report data
67
     *
68
     * @param Report $report The report with potential violations.
69
     * @param array $data The report output to add the violations to.
70
     * @return array The report output with violations, if any.
71
     */
72 2
    protected function addViolationsToReport(Report $report, array $data)
73
    {
74 2
        $rules = array();
75 2
        $results = array();
76 2
        $ruleIndices = array();
77
78
        /** @var RuleViolation $violation */
79 2
        foreach ($report->getRuleViolations() as $violation) {
80 1
            $rule = $violation->getRule();
81 1
            $ruleRef = str_replace(' ', '', $rule->getRuleSetName()) . '/' . $rule->getName();
82
83 1
            if (!isset($ruleIndices[$ruleRef])) {
84 1
                $ruleIndices[$ruleRef] = count($rules);
85
86 1
                $ruleData = array(
87 1
                    'id' => $ruleRef,
88 1
                    'name' => $rule->getName(),
89
                    'shortDescription' => array(
90 1
                        'text' => $rule->getRuleSetName() . ': ' . $rule->getName(),
91
                    ),
92
                    'messageStrings' => array(
93
                        'default' => array(
94 1
                            'text' => trim($rule->getMessage()),
95
                        ),
96
                    ),
97
                    'help' => array(
98 1
                        'text' => trim(str_replace("\n", ' ', $rule->getDescription())),
99
                    ),
100 1
                    'helpUri' => $rule->getExternalInfoUrl(),
101
                    'properties' => array(
102 1
                        'ruleSet' => $rule->getRuleSetName(),
103 1
                        'priority' => $rule->getPriority(),
104
                    ),
105
                );
106
107 1
                $examples = $rule->getExamples();
108 1
                if (!empty($examples)) {
109 1
                    $ruleData['help']['markdown'] =
110 1
                        $ruleData['help']['text'] .
111 1
                        "\n\n### Example\n\n```php\n" .
112 1
                        implode("\n```\n\n```php\n", array_map('trim', $examples)) . "\n```";
113
                }
114
115 1
                $since = $rule->getSince();
116 1
                if ($since) {
117 1
                    $ruleData['properties']['since'] = 'PHPMD ' . $since;
118
                }
119
120 1
                $rules[] = $ruleData;
121
            }
122
123 1
            $arguments = $violation->getArgs();
124 1
            if ($arguments === null) {
125 1
                $arguments = array();
126
            }
127
128 1
            $results[] = array(
129 1
                'ruleId' => $ruleRef,
130 1
                'ruleIndex' => $ruleIndices[$ruleRef],
131
                'message' => array(
132 1
                    'id' => 'default',
133 1
                    'arguments' => array_map('strval', $arguments),
134 1
                    'text' => $violation->getDescription(),
135
                ),
136
                'locations' => array(
137
                    array(
138
                        'physicalLocation' => array(
139 1
                            'artifactLocation' => static::pathToArtifactLocation($violation->getFileName()),
140
                            'region' => array(
141 1
                                'startLine' => $violation->getBeginLine(),
142 1
                                'endLine' => $violation->getEndLine(),
143
                            ),
144
                        ),
145
                    )
146
                ),
147
            );
148
        }
149
150 2
        $data['runs'][0]['tool']['driver']['rules'] = $rules;
151 2
        $data['runs'][0]['results'] = array_merge($data['runs'][0]['results'], $results);
152
153 2
        return $data;
154
    }
155
156
    /**
157
     * Add errors, if any, to the report data
158
     *
159
     * @param Report $report The report with potential errors.
160
     * @param array $data The report output to add the errors to.
161
     * @return array The report output with errors, if any.
162
     */
163 2
    protected function addErrorsToReport(Report $report, array $data)
164
    {
165 2
        $errors = $report->getErrors();
166 2
        if ($errors) {
0 ignored issues
show
introduced by
$errors is of type ArrayIterator, thus it always evaluated to true.
Loading history...
167 2
            foreach ($errors as $error) {
168 1
                $data['runs'][0]['results'][] = array(
169 1
                    'level' => 'error',
170
                    'message' => array(
171 1
                        'text' => $error->getMessage(),
172
                    ),
173
                    'locations' => array(
174
                        array(
175
                            'physicalLocation' => array(
176 1
                                'artifactLocation' => static::pathToArtifactLocation($error->getFile()),
177
                            ),
178
                        )
179
                    ),
180
                );
181
            }
182
        }
183
184 2
        return $data;
185
    }
186
187
    /**
188
     * Makes an absolute path relative to the working directory
189
     * if possible, otherwise prepends the `file://` protocol
190
     * and returns the result as a SARIF `artifactLocation`
191
     *
192
     * @param string $path
193
     * @return array
194
     */
195 2
    protected static function pathToArtifactLocation($path)
196
    {
197 2
        $workingDir = getcwd();
198 2
        if (substr($path, 0, strlen($workingDir)) === $workingDir) {
199
            // relative path
200
            return array(
201 2
                'uri' => substr($path, strlen($workingDir) + 1),
202 2
                'uriBaseId' => 'WORKINGDIR',
203
            );
204
        }
205
        
206
        // absolute path with protocol
207
        return array(
208 2
            'uri' => static::pathToUri($path),
209
        );
210
    }
211
212
    /**
213
     * Converts an absolute path to a file:// URI
214
     *
215
     * @param string $path
216
     * @return string
217
     */
218 2
    protected static function pathToUri($path)
219
    {
220 2
        $path = str_replace(DIRECTORY_SEPARATOR, '/', $path);
221
222
        // file:///C:/... on Windows systems
223 2
        if (substr($path, 0, 1) !== '/') {
224
            $path = '/' . $path;
225
        }
226
227 2
        return 'file://' . $path;
228
    }
229
}
230