Completed
Push — master ( 5bfa5e...03b9ab )
by Richard
03:43
created

Queries::last_run()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 2.003

Importance

Changes 0
Metric Value
dl 0
loc 14
ccs 10
cts 11
cp 0.9091
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 12
nc 2
nop 0
crap 2.003
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 25
    public function __construct(ResultDB $result_db) {
15 25
        $this->result_db = $result_db;
16 25
    }
17
18
    /**
19
     * Get the id of the last run.
20
     *
21
     * @return  int
22
     */
23 10
    public function last_run() {
24 10
        $b = $this->result_db->builder();
25
        $res = $b
26 10
            ->select("id")
27 10
            ->from("runs")
28 10
            ->orderBy("id", "DESC")
29 10
            ->setMaxResults(1)
30 10
            ->execute()
31 10
            ->fetch();
32 10
        if ($res) {
33 10
            return (int)$res["id"];
34
        }
35
        throw new \RuntimeException("Result database contains no runs.");
36
    }
37
38
    /**
39
     * Get the id of the last run for a certain commit.
40
     *
41
     * @param   string  $commit_hash
42
     * @return  int|null
43
     */
44 10 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...
45 10
        $b = $this->result_db->builder();
46
        $res = $b
47 10
            ->select("id")
48 10
            ->from("runs")
49 10
            ->where("commit_hash = ?")
50 10
            ->setParameter(0, $commit_hash)
51 10
            ->orderBy("id", "DESC")
52 10
            ->setMaxResults(1)
53 10
            ->execute()
54 10
            ->fetch();
55 10
        if ($res) {
56 10
            return (int)$res["id"];
57
        }
58
        throw new \RuntimeException("Result database contains no run for commit '$commit_hash'.");
59
    }
60
61
    /**
62
     * Get the id of the run before the given run.
63
     *
64
     * @param   int     $run
65
     * @return  int
66
     */
67 1 View Code Duplication
    public function run_before($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...
68 1
        $b = $this->result_db->builder();
69
        $res = $b
70 1
            ->select("id")
71 1
            ->from("runs")
72 1
            ->where("id < ?")
73 1
            ->setParameter(0, $run)
74 1
            ->orderBy("id", "DESC")
75 1
            ->setMaxResults(1)
76 1
            ->execute();
77 1
        $res = $res->fetch();
78 1
        if ($res) {
79 1
            return (int)$res["id"];
80
        }
81
        throw new \RuntimeException("Result database contains no run before '$run'.");
82
    }
83
84
    /**
85
     * Get the id of the run before the given run that has another commit as the
86
     * given run.
87
     *
88
     * @param   int     $run
89
     * @return  int
90
     */
91 2
    public function run_with_different_commit_before($run) {
92 2
        $commit_hash = $this->run_info($run)["commit_hash"];
93 2
        $b = $this->result_db->builder();
94
        $res = $b
95 2
            ->select("id")
96 2
            ->from("runs")
97 2
            ->where("commit_hash <> ? AND id < ?")
98 2
            ->setParameter(0, $commit_hash)
99 2
            ->setParameter(1, $run)
100 2
            ->orderBy("id", "DESC")
101 2
            ->setMaxResults(1)
102 2
            ->execute()
103 2
            ->fetch();
104 2
        if ($res) {
105 2
            return (int)$res["id"];
106
        }
107
        throw new \RuntimeException("Result database contains previous run with a different commit.");
108
    }
109
110
    /**
111
     * Get information about a run.
112
     *
113
     * @param   int $run
114
     * @return  array<string,string>     with keys 'commit_hash'
115
     */
116 4 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...
117 4
        $b = $this->result_db->builder();
118
        $res = $b
119 4
            ->select("commit_hash")
120 4
            ->from("runs")
121 4
            ->where("id = ?")
122 4
            ->setParameter(0, $run)
123 4
            ->execute()
124 4
            ->fetch();
125 4
        if ($res) {
126 4
            return $res;
127
        }
128
        throw new \RuntimeException("Result database contains no run with id '$run'.");
129
    }
130
131
    /**
132
     * Get the amount of violations in a run.
133
     *
134
     * @param   int         $run
135
     * @param   int|null    $rule
136
     * @return  int
137
     */
138 5
    public function count_violations_in($run, $rule = null) {
139 5
        $b = $this->result_db->builder();
140
        $q = $b
141 5
            ->select("COUNT(*) cnt")
142 5
            ->from("runs", "rs")
143 5
            ->innerJoin("rs", "violations", "vs",
144 5
                "rs.id >= vs.first_seen AND rs.id <= vs.last_seen")
145 5
            ->innerJoin("vs", "violation_locations", "vls",
146 5
                "vs.id = vls.violation_id AND rs.id = vls.run_id")
147 5
            ->where("rs.id = ?")
148 5
            ->setParameter(0, $run);
149 5
        if ($rule !== null) {
150
            $q = $q
151 3
                ->andWhere("vs.rule_id = ?")
152 3
                ->setParameter(1, $rule);
153 3
        }
154
        $res = $q
155 5
            ->execute()
156 5
            ->fetch();
157 5
        if ($res) {
158 5
            return (int)$res["cnt"];
159
        }
160
        throw new \RuntimeException("Result database contains no run with id '$run'.");
161
    }
162
163
    /**
164
     * Get the amount of violations that were added in a run.
165
     *
166
     * @param   int         $run_former
167
     * @param   int         $run_latter
168
     * @param   int|null    $rule
169
     * @return  int
170
     */
171 4 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...
172 4
        $b = $this->result_db->builder();
173
        $q = $b
174 4
            ->select(
175
                "(SELECT COUNT (*) ".
176 4
                "FROM violation_locations vls ".
177 4
                "WHERE vls.run_id = :former AND vls.violation_id = vs.id) cnt_former")
178 4
            ->addSelect(
179
                "(SELECT COUNT (*) ".
180 4
                "FROM violation_locations vls ".
181 4
                "WHERE vls.run_id = :latter AND vls.violation_id = vs.id) cnt_latter")
182 4
            ->from("violations", "vs")
183 4
            ->where("cnt_former < cnt_latter")
184 4
            ->setParameter("former", $run_former)
185 4
            ->setParameter("latter", $run_latter);
186 4
        if ($rule !== null) {
187
            $q = $q
188 2
                ->andWhere("vs.rule_id = :rule")
189 2
                ->setParameter("rule", $rule);
190 2
        }
191 4
        $rows = $q->execute();
192 4
        $res = 0;
193 4
        while($r = $rows->fetch()) {
194 4
            if ((int)$r["cnt_latter"] > (int)$r["cnt_former"]) {
195 4
                $res += (int)$r["cnt_latter"] - (int)$r["cnt_former"];
196 4
            }
197 4
        }
198 4
        return $res;
199
    }
200
201
    /**
202
     * Get the amount of violations that were resolved in a run.
203
     *
204
     * @param   int         $run_former
205
     * @param   int         $run_latter
206
     * @param   int|null    $rule
207
     * @return  int
208
     */
209 4 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...
210 4
        $b = $this->result_db->builder();
211
        $q = $b
212 4
            ->select(
213
                "(SELECT COUNT (*) ".
214 4
                "FROM violation_locations vls ".
215 4
                "WHERE vls.run_id = :former AND vls.violation_id = vs.id) cnt_former")
216 4
            ->addSelect(
217
                "(SELECT COUNT (*) ".
218 4
                "FROM violation_locations vls ".
219 4
                "WHERE vls.run_id = :latter AND vls.violation_id = vs.id) cnt_latter")
220 4
            ->from("violations", "vs")
221 4
            ->where("cnt_former > cnt_latter")
222 4
            ->setParameter("former", $run_former)
223 4
            ->setParameter("latter", $run_latter);
224 4
        if ($rule !== null) {
225
            $q = $q
226 2
                ->andWhere("vs.rule_id = :rule")
227 2
                ->setParameter("rule", $rule);
228 2
        }
229 4
        $rows = $q->execute();
230 4
        $res = 0;
231 4
        while($r = $rows->fetch()) {
232 4
            if ((int)$r["cnt_former"] > (int)$r["cnt_latter"]) {
233 4
                $res += (int)$r["cnt_former"] - (int)$r["cnt_latter"];
234 4
            }
235 4
        }
236 4
        return $res;
237
    }
238
239
    /**
240
     * Get the rules that were analyzed in a run.
241
     *
242
     * @param   int $run
243
     * @return  int[]
244
     */
245 8
    public function analyzed_rules($run) {
246 8
        $b = $this->result_db->builder();
247
        $res = $b
248 8
            ->select("rrs.id")
249 8
            ->from("runs", "rs")
250 8
            ->innerJoin("rs", "rules", "rrs",
251 8
                "rs.id >= rrs.first_seen AND rs.id <= rrs.last_seen")
252 8
            ->where("rs.id = ?")
253 8
            ->setParameter(0, $run)
254 8
            ->execute()
255 8
            ->fetchAll();
256
        return array_map(function($r) { return $r["id"]; }, $res);
257
    }
258
259
    /**
260
     * Get information about a rule.
261
     *
262
     * @param   int $rule
263
     * @return  array<string,string>    with keys 'rule', 'explanation'
264
     */
265 7 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...
266 7
        $b = $this->result_db->builder();
267
        $res = $b
268 7
            ->select("rule", "explanation")
269 7
            ->from("rules")
270 7
            ->where("rules.id = ?")
271 7
            ->setParameter(0, $rule)
272 7
            ->execute()
273 7
            ->fetch();
274 7
        if ($res) {
275 7
            return $res;
276
        }
277
        throw new \RuntimeException("Result database contains no rule with id '$rule'.");
278
    }
279
280
    /**
281
     * Get the violations of a rule.
282
     *
283
     * @param   int $rule
284
     * @param   int $run
285
     * @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 26. [(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...
286
     */
287 3
    public function violations_of($rule, $run) {
288 3
        $b = $this->result_db->builder();
289
        return $b
290 3
            ->select("vs.file", "vls.line_no", "vs.first_seen introduced_in")
291 3
            ->from("runs", "rs")
292 3
            ->innerJoin("rs", "violations", "vs",
293 3
                "rs.id >= vs.first_seen AND rs.id <= vs.last_seen")
294 3
            ->innerJoin("vs", "violation_locations", "vls",
295 3
                "vs.id = vls.violation_id AND rs.id = vls.run_id")
296 3
            ->where("rs.id = ?")
297 3
            ->andWhere("vs.rule_id = ?")
298 3
            ->setParameter(0, $run)
299 3
            ->setParameter(1, $rule)
300 3
            ->execute()
301 3
            ->fetchAll();
302
    }
303
}
304