Completed
Push — master ( 86b2cd...b16d12 )
by Richard
03:26
created

Queries::count_resolved_violations()   B

Complexity

Conditions 4
Paths 6

Size

Total Lines 29
Code Lines 25

Duplication

Lines 29
Ratio 100 %

Importance

Changes 0
Metric Value
cc 4
eloc 25
nc 6
nop 3
dl 29
loc 29
rs 8.5806
c 0
b 0
f 0
1
<?php
2
3
namespace Lechimp\Dicto\Report;
4
5
/**
6
 * Queries on the ResultDB.
7
 */
8
class Queries {
9
    /**
10
     * @var ResultDB
11
     */
12
    protected $result_db;
13
14
    public function __construct(ResultDB $result_db) {
15
        $this->result_db = $result_db;
16
    }
17
18
    /**
19
     * Get the id of the current run.
20
     *
21
     * @return  int
22
     */
23
    public function current_run() {
24
        $b = $this->result_db->builder();
25
        $res = $b
26
            ->select("id")
27
            ->from("runs")
28
            ->orderBy("id", "DESC")
29
            ->setMaxResults(1)
30
            ->execute()
31
            ->fetch();
32
        if ($res) {
33
            return (int)$res["id"];
34
        }
35
        throw new \RuntimeException("Result database contains no runs.");
36
    }
37
38
    /**
39
     * Get the id of the previous run.
40
     *
41
     * @return  int
42
     */
43 View Code Duplication
    public function previous_run() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
44
        $b = $this->result_db->builder();
45
        $res = $b
46
            ->select("id")
47
            ->from("runs")
48
            ->orderBy("id", "DESC")
49
            ->setMaxResults(2)
50
            ->execute();
51
        // Drop current
52
        $res->fetch();
53
        $res = $res->fetch();
54
        if ($res) {
55
            return (int)$res["id"];
56
        }
57
        throw new \RuntimeException("Result database contains no previous run.");
58
    }
59
60
    /**
61
     * Get the id of previous run with another commit id as current run.
62
     *
63
     * @return  int
64
     */
65
    public function previous_run_with_different_commit() {
66
        $cur = $this->current_run();
67
        $commit_hash = $this->run_info($cur)["commit_hash"];
68
        $b = $this->result_db->builder();
69
        $res = $b
70
            ->select("id")
71
            ->from("runs")
72
            ->where("commit_hash <> ?")
73
            ->setParameter(0, $commit_hash)
74
            ->orderBy("id", "DESC")
75
            ->setMaxResults(1)
76
            ->execute()
77
            ->fetch();
78
        if ($res) {
79
            return (int)$res["id"];
80
        }
81
        throw new \RuntimeException("Result database contains previous run with a different commit.");
82
    }
83
84
    /**
85
     * Get the id of the last run for a certain commit.
86
     *
87
     * @param   string  $commit_hash
88
     * @return  int|null
89
     */
90 View Code Duplication
    public function last_run_for($commit_hash) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
91
        $b = $this->result_db->builder();
92
        $res = $b
93
            ->select("id")
94
            ->from("runs")
95
            ->where("commit_hash = ?")
96
            ->setParameter(0, $commit_hash)
97
            ->orderBy("id", "DESC")
98
            ->setMaxResults(1)
99
            ->execute()
100
            ->fetch();
101
        if ($res) {
102
            return (int)$res["id"];
103
        }
104
        throw new \RuntimeException("Result database contains no runs.");
105
    }
106
107
    /**
108
     * Get information about a run.
109
     *
110
     * @param   int $run
111
     * @return  array<string,string>     with keys 'commit_hash'
112
     */
113 View Code Duplication
    public function run_info($run) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
114
        $b = $this->result_db->builder();
115
        $res = $b
116
            ->select("commit_hash")
117
            ->from("runs")
118
            ->where("id = ?")
119
            ->setParameter(0, $run)
120
            ->execute()
121
            ->fetch();
122
        if ($res) {
123
            return $res;
124
        }
125
        throw new \RuntimeException("Result database contains no run with id '$run'.");
126
    }
127
128
    /**
129
     * Get the amount of violations in a run.
130
     *
131
     * @param   int         $run
132
     * @param   int|null    $rule
133
     * @return  int
134
     */
135
    public function count_violations_in($run, $rule = null) {
136
        $b = $this->result_db->builder();
137
        $q = $b
138
            ->select("COUNT(*) cnt")
139
            ->from("runs", "rs")
140
            ->innerJoin("rs", "violations", "vs",
141
                "rs.id >= vs.first_seen AND rs.id <= vs.last_seen")
142
            ->innerJoin("vs", "violation_locations", "vls",
143
                "vs.id = vls.violation_id AND rs.id = vls.run_id")
144
            ->where("rs.id = ?")
145
            ->setParameter(0, $run);
146
        if ($rule !== null) {
147
            $q = $q
148
                ->andWhere("vs.rule_id = ?")
149
                ->setParameter(1, $rule);
150
        }
151
        $res = $q
152
            ->execute()
153
            ->fetch();
154
        if ($res) {
155
            return (int)$res["cnt"];
156
        }
157
        throw new \RuntimeException("Result database contains no run with id '$run'.");
158
    }
159
160
    /**
161
     * Get the amount of violations that were added in a run.
162
     *
163
     * @param   int         $run_former
164
     * @param   int         $run_latter
165
     * @param   int|null    $rule
166
     * @return  int
167
     */
168 View Code Duplication
    public function count_added_violations($run_former, $run_latter, $rule = null) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
169
        $b = $this->result_db->builder();
170
        $q = $b
171
            ->select(
172
                "(SELECT COUNT (*) ".
173
                "FROM violation_locations vls ".
174
                "WHERE vls.run_id = :former AND vls.violation_id = vs.id) cnt_former")
175
            ->addSelect(
176
                "(SELECT COUNT (*) ".
177
                "FROM violation_locations vls ".
178
                "WHERE vls.run_id = :latter AND vls.violation_id = vs.id) cnt_latter")
179
            ->from("violations", "vs")
180
            ->where("cnt_former < cnt_latter")
181
            ->setParameter("former", $run_former)
182
            ->setParameter("latter", $run_latter);
183
        if ($rule !== null) {
184
            $q = $q
185
                ->andWhere("vs.rule_id = :rule")
186
                ->setParameter("rule", $rule);
187
        }
188
        $rows = $q->execute();
189
        $res = 0;
190
        while($r = $rows->fetch()) {
191
            if ((int)$r["cnt_latter"] > (int)$r["cnt_former"]) {
192
                $res += (int)$r["cnt_latter"] - (int)$r["cnt_former"];
193
            }
194
        }
195
        return $res;
196
    }
197
198
    /**
199
     * Get the amount of violations that were resolved in a run.
200
     *
201
     * @param   int         $run_former
202
     * @param   int         $run_latter
203
     * @param   int|null    $rule
204
     * @return  int
205
     */
206 View Code Duplication
    public function count_resolved_violations($run_former, $run_latter, $rule = null) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
207
        $b = $this->result_db->builder();
208
        $q = $b
209
            ->select(
210
                "(SELECT COUNT (*) ".
211
                "FROM violation_locations vls ".
212
                "WHERE vls.run_id = :former AND vls.violation_id = vs.id) cnt_former")
213
            ->addSelect(
214
                "(SELECT COUNT (*) ".
215
                "FROM violation_locations vls ".
216
                "WHERE vls.run_id = :latter AND vls.violation_id = vs.id) cnt_latter")
217
            ->from("violations", "vs")
218
            ->where("cnt_former > cnt_latter")
219
            ->setParameter("former", $run_former)
220
            ->setParameter("latter", $run_latter);
221
        if ($rule !== null) {
222
            $q = $q
223
                ->andWhere("vs.rule_id = :rule")
224
                ->setParameter("rule", $rule);
225
        }
226
        $rows = $q->execute();
227
        $res = 0;
228
        while($r = $rows->fetch()) {
229
            if ((int)$r["cnt_former"] > (int)$r["cnt_latter"]) {
230
                $res += (int)$r["cnt_former"] - (int)$r["cnt_latter"];
231
            }
232
        }
233
        return $res;
234
    }
235
236
    /**
237
     * Get the rules that were analyzed in a run.
238
     *
239
     * @param   int $run
240
     * @return  int[]
241
     */
242 View Code Duplication
    public function analyzed_rules($run) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
243
        $b = $this->result_db->builder();
244
        $res = $b
245
            ->select("rrs.id")
246
            ->from("runs", "rs")
247
            ->innerJoin("rs", "rules", "rrs",
248
                "rs.id >= rrs.first_seen AND rs.id <= rrs.last_seen")
249
            ->where("rs.id = ?")
250
            ->setParameter(0, $run)
251
            ->execute()
252
            ->fetchAll();
253
        return array_map(function($r) { return $r["id"]; }, $res);
254
    }
255
256
    /**
257
     * Get information about a rule.
258
     *
259
     * @param   int $rule
260
     * @return  array<string,string>    with keys 'rule', 'explanation'
261
     */
262 View Code Duplication
    public function rule_info($rule) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
263
        $b = $this->result_db->builder();
264
        $res = $b
265
            ->select("rule", "explanation")
266
            ->from("rules")
267
            ->where("rules.id = ?")
268
            ->setParameter(0, $rule)
269
            ->execute()
270
            ->fetch();
271
        if ($res) {
272
            return $res;
273
        }
274
        throw new \RuntimeException("Result database contains no rule with id '$rule'.");
275
    }
276
277
    /**
278
     * Get the violations of a rule.
279
     *
280
     * @param   int $rule
281
     * @param   int $run
282
     * @return  array<string,string|int>[]  with keys 'file', 'line_no', 'introduced_in'
0 ignored issues
show
Documentation introduced by
The doc-type array<string,string|int>[] could not be parsed: Expected "|" or "end of type", but got "" at position 24. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
283
     */
284
    public function violations_of($rule, $run) {
285
        $b = $this->result_db->builder();
286
        return $b
287
            ->select("vs.file", "vls.line_no", "vs.first_seen introduced_in")
288
            ->from("runs", "rs")
289
            ->innerJoin("rs", "violations", "vs",
290
                "rs.id >= vs.first_seen AND rs.id <= vs.last_seen")
291
            ->innerJoin("vs", "violation_locations", "vls",
292
                "vs.id = vls.violation_id AND rs.id = vls.run_id")
293
            ->where("rs.id = ?")
294
            ->andWhere("vs.rule_id = ?")
295
            ->setParameter(0, $run)
296
            ->setParameter(1, $rule)
297
            ->execute()
298
            ->fetchAll();
299
    }
300
}
301