Completed
Push — master ( 178b4a...1f981d )
by Richard
06:19
created

ResultDB::violation_id()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 21
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 21
ccs 17
cts 17
cp 1
rs 9.3142
cc 2
eloc 17
nc 2
nop 1
crap 2
1
<?php
2
/******************************************************************************
3
 * An implementation of dicto (scg.unibe.ch/dicto) in and for PHP.
4
 *
5
 * Copyright (c) 2016, 2015 Richard Klees <[email protected]>
6
 *
7
 * This software is licensed under The MIT License. You should have received
8
 * a copy of the license along with the code.
9
 */
10
11
namespace Lechimp\Dicto\App;
12
13
use Lechimp\Dicto\Analysis\ReportGenerator;
14
use Lechimp\Dicto\Analysis\Violation;
15
use Lechimp\Dicto\Rules\Ruleset;
16
use Lechimp\Dicto\Rules\Rule;
17
use Doctrine\DBAL\Schema;
18
use Doctrine\DBAL\Types\Type;
19
use Doctrine\DBAL\Schema\Synchronizer\SingleDatabaseSynchronizer;
20
21
class ResultDB extends DB implements ReportGenerator {
22
    /**
23
     * @var int|null
24
     */
25
    private $current_run_id = null;
26
27
    /**
28
     * @var int|null
29
     */
30
    private $current_rule_id = null;
31
32
    // ReportGenerator implementation
33
34
    /**
35
     * Announce to start a new run of the analysis now.
36
     *
37
     * @param   string  $commit_hash
38
     * @return  null
39
     */
40 15
    public function begin_new_run($commit_hash) {
41 15
        assert('is_string($commit_hash)');
42 15
        $this->builder()
43 15
            ->insert($this->run_table())
44 15
            ->values(array
45
                ( "commit_hash" => "?"
46 15
                ))
47 15
            ->setParameter(0, $commit_hash)
48 15
            ->execute();
49 15
        $this->current_run_id = (int)$this->connection->lastInsertId();
50 15
    }
51
52
    /**
53
     * @inheritdoc
54
     */
55
    public function begin_ruleset(Ruleset $rule) {
56
        // Nothing to do here...
57
    }
58
59
    /**
60
     * @inheritdoc
61
     */
62
    public function end_ruleset(Ruleset $rule) {
63
        // Nothing to do here...
64
    }
65
66
    /**
67
     * @inheritdoc
68
     */
69 9
    public function begin_rule(Rule $rule) {
70 9
        assert('$this->current_run_id !== null');
71 9
        $rule_id = $this->rule_id($rule);
72 9
        if ($rule_id === null) {
73 9
            $this->builder()
74 9
                ->insert($this->rule_table())
75 9
                ->values(array
76
                    ( "rule" => "?"
77 9
                    , "first_seen" => "?"
78 9
                    , "last_seen" => "?"
79 9
                    ))
80 9
                ->setParameter(0, $rule->pprint())
81 9
                ->setParameter(1, $this->current_run_id)
82 9
                ->setParameter(2, $this->current_run_id)
83 9
                ->execute();
84 9
            $rule_id = (int)$this->connection->lastInsertId();
85 9
        }
86 View Code Duplication
        else {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
87 5
            $this->builder()
88 5
                ->update($this->rule_table())
89 5
                ->set("last_seen", "?")
90 5
                ->where("id = ?")
91 5
                ->setParameter(0, $this->current_run_id)
92 5
                ->setParameter(1, $rule_id)
93 5
                ->execute();
94
        }
95 9
        $this->current_rule_id = $rule_id;
96 9
    }
97
98
    /**
99
     * @inheritdoc
100
     */
101
    public function end_rule(Rule $rule) {
102
        $this->current_rule_id = null;
103
    }
104
105
    /**
106
     * @inheritdoc
107
     */
108 7
    public function report_violation(Violation $violation) {
109 7
        assert('$this->current_run_id !== null');
110 7
        assert('$this->current_rule_id !== null');
111 7
        $violation_id = $this->violation_id($violation);
112 7
        if ($violation_id === null) {
113 7
            $this->builder()
114 7
                ->insert($this->violation_table())
115 7
                ->values(array
116
                    ( "rule_id" => "?"
117 7
                    , "file" => "?"
118 7
                    , "line" => "?"
119 7
                    , "first_seen" => "?"
120 7
                    , "last_seen" => "?"
121 7
                    ))
122 7
                ->setParameter(0, $this->current_rule_id)
123 7
                ->setParameter(1, $violation->filename())
124 7
                ->setParameter(2, $violation->line())
125 7
                ->setParameter(3, $this->current_run_id)
126 7
                ->setParameter(4, $this->current_run_id)
127 7
                ->execute();
128 7
            $violation_id = (int)$this->connection->lastInsertId();
129 7
        }
130 View Code Duplication
        else {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
131 3
            $this->builder()
132 3
                ->update($this->violation_table())
133 3
                ->set("last_seen", "?")
134 3
                ->where("id = ?")
135 3
                ->setParameter(0, $this->current_run_id)
136 3
                ->setParameter(1, $violation_id)
137 3
                ->execute();
138
        }
139
140 7
        $this->builder()
141 7
            ->insert($this->violation_location_table())
142 7
            ->values(array
143
                ( "violation_id" => "?"
144 7
                , "run_id"  => "?"
145 7
                , "line_no" => "?"
146 7
                ))
147 7
            ->setParameter(0, $violation_id)
148 7
            ->setParameter(1, $this->current_run_id)
149 7
            ->setParameter(2, $violation->line_no())
150 7
            ->execute();
151 7
    }
152
153
    // Helpers
154
155
    /**
156
     * @param   Rule    $rule
157
     * @return  int|null
158
     */
159 9
    protected function rule_id(Rule $rule) {
160 9
        $res = $this->builder()
161 9
            ->select("id")
162 9
            ->from($this->rule_table())
163 9
            ->where("rule = ?")
164 9
            ->setParameter(0, $rule->pprint())
165 9
            ->execute()
166 9
            ->fetch();
167 9
        if ($res) {
168 5
            return (int)$res["id"];
169
        }
170
        else {
171 9
            return null;
172
        }
173
    }
174
175
    /**
176
     * @param   Violation   $violation
177
     * @return  int|null
178
     */
179 7
    protected function violation_id(Violation $violation) {
180 7
        $res = $this->builder()
181 7
            ->select("id")
182 7
            ->from($this->violation_table())
183 7
            ->where($this->builder()->expr()->andX
184 7
                ( "rule_id = ?"
185 7
                , "file = ?"
186 7
                , "line = ?"
187 7
                ))
188 7
            ->setParameter(0, $this->current_rule_id)
189 7
            ->setParameter(1, $violation->filename())
190 7
            ->setParameter(2, $violation->line())
191 7
            ->execute()
192 7
            ->fetch();
193 7
        if ($res) {
194 3
            return (int)$res["id"];
195
        }
196
        else {
197 7
            return null;
198
        }
199
    }
200
201
    // Names
202
203 17
    public function run_table() {
204 17
        return "runs";    
205
    }
206
207
    public function variable_table() {
208
        return "variables";
209
    }
210
211 17
    public function rule_table() {
212 17
        return "rules";
213
    }
214
215 17
    public function violation_table() {
216 17
        return "violations";
217
    }
218
219 17
    public function violation_location_table() {
220 17
        return "violation_locations";
221
    }
222
223
    // Creation of database.
224
225 17
    public function init_database_schema() {
226 17
        $schema = new Schema\Schema();
227
228 17
        $run_table = $schema->createTable($this->run_table());
229 17
        $run_table->addColumn
230 17
            ("id", "integer"
231 17
            , array("notnull" => true, "unsigned" => true, "autoincrement" => true)
232 17
            );
233 17
        $run_table->addColumn
234 17
            ( "commit_hash", "string"
235 17
            , array("notnull" => true)
236 17
            );
237
        // TODO: maybe add time
238
        // TODO: do we need some other meta information per run of the analysis? 
239 17
        $run_table->setPrimaryKey(array("id"));
240
241
        // TODO: looks like i need to add the variable definitions as well
242
243 17
        $rule_table = $schema->createTable($this->rule_table());
244 17
        $rule_table->addColumn
245 17
            ( "id", "integer"
246 17
            , array("notnull" => true)
247 17
            );
248 17
        $rule_table->addColumn
249 17
            ( "rule", "string"
250 17
            , array("notnull" => true)
251 17
            );
252 17
        $rule_table->addColumn
253 17
            ( "first_seen", "integer"
254 17
            , array("notnull" => true)
255 17
            );
256 17
        $rule_table->addColumn
257 17
            ( "last_seen", "integer"
258 17
            , array("notnull" => true)
259 17
            );
260 17
        $rule_table->setPrimaryKey(array("id"));
261 17
        $rule_table->addUniqueIndex(array("rule"));
262 17
        $rule_table->addForeignKeyConstraint
263 17
            ( $run_table
264 17
            , array("first_seen")
265 17
            , array("id")
266 17
            );
267 17
        $rule_table->addForeignKeyConstraint
268 17
            ( $run_table
269 17
            , array("last_seen")
270 17
            , array("id")
271 17
            );
272
273 17
        $violation_table = $schema->createTable($this->violation_table());
274 17
        $violation_table->addColumn
275 17
            ( "id", "integer"
276 17
            , array("notnull" => true, "unsigned" => true, "autoincrement" => true)
277 17
            );
278 17
        $violation_table->addColumn
279 17
            ( "rule_id", "integer"
280 17
            , array("notnull" => true)
281 17
            );
282 17
        $violation_table->addColumn
283 17
            ( "file", "string"
284 17
            , array("notnull" => true)
285 17
            );
286 17
        $violation_table->addColumn
287 17
            ( "line", "string"
288 17
            , array("notnull" => true)
289 17
            );
290 17
        $violation_table->addColumn
291 17
            ( "first_seen", "integer"
292 17
            , array("notnull" => true)
293 17
            );
294 17
        $violation_table->addColumn
295 17
            ( "last_seen", "integer"
296 17
            , array("notnull" => true)
297 17
            );
298 17
        $violation_table->setPrimaryKey(array("id"));
299 17
        $violation_table->addUniqueIndex(array("rule_id", "file", "line"));
300 17
        $violation_table->addForeignKeyConstraint
301 17
            ( $rule_table
302 17
            , array("rule_id")
303 17
            , array("id")
304 17
            );
305 17
        $violation_table->addForeignKeyConstraint
306 17
            ( $run_table
307 17
            , array("first_seen")
308 17
            , array("id")
309 17
            );
310 17
        $violation_table->addForeignKeyConstraint
311 17
            ( $run_table
312 17
            , array("last_seen")
313 17
            , array("id")
314 17
            );
315
316 17
        $violation_location_table = $schema->createTable($this->violation_location_table());
317
318 17
        $violation_location_table->addColumn
319 17
            ( "id", "integer"
320 17
            , array("notnull" => true, "unsigned" => true, "autoincrement" => true)
321 17
            );
322 17
        $violation_location_table->addColumn
323 17
            ( "violation_id", "integer"
324 17
            , array("notnull" => true)
325 17
            );
326 17
        $violation_location_table->addColumn
327 17
            ( "run_id", "integer"
328 17
            , array("notnull" => true)
329 17
            );
330 17
        $violation_location_table->addColumn
331 17
            ( "line_no", "integer"
332 17
            , array("notnull" => true)
333 17
            );
334 17
        $violation_location_table->setPrimaryKey(array("id"));
335 17
        $violation_location_table->addForeignKeyConstraint
336 17
            ( $violation_table
337 17
            , array("violation_id")
338 17
            , array("id")
339 17
            );
340 17
        $violation_location_table->addForeignKeyConstraint
341 17
            ( $run_table
342 17
            , array("run_id")
343 17
            , array("id")
344 17
            );
345
346 17
        $sync = new SingleDatabaseSynchronizer($this->connection);
347 17
        $sync->createSchema($schema);
348 17
    }
349
}
350