Completed
Push — master ( f7852e...e666ea )
by Richard
06:08
created

IndexDB::init_relation_table()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 44
Code Lines 34

Duplication

Lines 44
Ratio 100 %

Importance

Changes 0
Metric Value
dl 44
loc 44
rs 8.8571
c 0
b 0
f 0
cc 1
eloc 34
nc 1
nop 3
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\Variables\Variable;
14
use Lechimp\Dicto\Analysis\Query;
15
use Lechimp\Dicto\Analysis\CompilesVars;
16
use Lechimp\Dicto\Indexer\Insert;
17
use Lechimp\Dicto\Indexer\CachesReferences;
18
use Doctrine\DBAL\Schema as S;
19
use Doctrine\DBAL\Types\Type;
20
use Doctrine\DBAL\Schema\Synchronizer\SingleDatabaseSynchronizer;
21
22
class IndexDB extends DB implements Insert, Query {
0 ignored issues
show
Bug introduced by
There is at least one abstract method in this class. Maybe declare it as abstract, or implement the remaining methods: _class, _file, _function, _function_reference, _global, _language_construct, _method, _method_reference, _relation
Loading history...
23
//    use CachesReferences;
24
25
    // Implementation of Insert interface.
26
27
    /**
28
     * @inheritdoc
29
     */
30
    public function name($name, $type) {
31
        assert('is_string($name)');
32
        assert('\\Lechimp\\Dicto\\Variables\\Variable::is_type($type)');
33
34
        $name_id = $this->get_int_id($name, $this->name_table(), "name");
35
        if ($name_id !== null) {
36
            return $name_id;
37
        }
38
39
        $this->builder()
40
            ->insert($this->name_table())
41
            ->values(array
42
                ( "name" => "?"
43
                , "type" => "?"
44
                ))
45
            ->setParameter(0, $name)
46
            ->setParameter(1, $type)
47
            ->execute();
48
        return (int)$this->connection->lastInsertId();
49
    }
50
51
    /**
52
     * Store a filename or just get its id if the file is already stored.
53
     *
54
     * @param   string      $path
55
     * @return  int
56
     */
57
    public function file($path) {
58
        assert('is_string($path)');
59
60
        $file_id = $this->get_int_id($path, $this->file_table(), "path");
61
        if ($file_id !== null) {
62
            return $file_id;
63
        }
64
65
        $this->builder()
66
            ->insert($this->file_table())
67
            ->values(array
68
                ( "path" => "?"
69
                ))
70
            ->setParameter(0, $path)
71
            ->execute();
72
        return (int)$this->connection->lastInsertId();
73
    }
74
75
    /**
76
     * @inheritdoc
77
     */
78
    public function source($path, $content) {
79
        assert('is_string($content)');
80
81
        $file_id = $this->file($path);
82
83
        $stmt = $this->builder()
84
            ->insert($this->source_table())
85
            ->values(array
86
                ( "file" => "?"
87
                , "line" => "?"
88
                , "source" => "?"
89
                ))
90
            ->setParameter(0, $file_id);
91
        $line = 1;
92
        foreach (explode("\n", $content) as $source) {
93
            $stmt
94
                ->setParameter(1, $line)
95
                ->setParameter(2, $source)
96
                ->execute();
97
            $line++;
98
        }
99
        return $file_id;
100
    }
101
102
    /**
103
     * @inheritdoc
104
     */
105
    public function definition($name, $type, $file, $start_line, $end_line) {
106
        assert('is_int($start_line)');
107
        assert('is_int($end_line)');
108
109
        $name_id = $this->name($name, $type);
110
        $file_id = $this->file($file);
111
112
        $this->builder()
113
            ->insert($this->definition_table())
114
            ->values(array
115
                ( "name" => "?"
116
                , "file" => "?"
117
                , "start_line" => "?"
118
                , "end_line" => "?"
119
                ))
120
            ->setParameter(0, $name_id)
121
            ->setParameter(1, $file_id)
122
            ->setParameter(2, $start_line)
123
            ->setParameter(3, $end_line)
124
            ->execute();
125
        return array($name_id, 0);
126
    }
127
128
    /**
129
     * @inheritdoc
130
     */
131
    public function method_info($name_id, $class_name_id, $definition_id) {
132
        $this->builder()
133
            ->insert($this->method_info_table())
134
            ->values(array
135
                ( "name" => "?"
136
                , "class" => "?"
137
                , "definition" => "?"
138
                ))
139
            ->setParameter(0, $name_id)
140
            ->setParameter(1, $class_name_id)
141
            ->setParameter(2, $definition_id)
142
            ->execute();
143
        return null;
144
    }
145
146
    /**
147
     * @inheritdoc
148
     */
149
    public function relation($name_left_id, $name_right_id, $which, $file, $line) {
150
        assert('is_int($name_left_id)');
151
        assert('is_int($name_right_id)');
152
        assert('is_string($which)');
153
        assert('is_int($line)');
154
155
        $file_id = $this->get_int_id($file, $this->file_table(), "path");
156
157
        assert('is_int($file_id)');
158
159
        $this->builder()
160
            ->insert($this->relation_table())
161
            ->values(array
162
                ( "name_left" => "?"
163
                , "name_right" => "?"
164
                , "which" => "?"
165
                , "file" => "?"
166
                , "line" => "?"
167
                ))
168
            ->setParameter(0, $name_left_id)
169
            ->setParameter(1, $name_right_id)
170
            ->setParameter(2, $which)
171
            ->setParameter(3, $file_id)
172
            ->setParameter(4, $line)
173
            ->execute();
174
    }
175
176
    /**
177
     * Get the numeric id for the stringy id in table by using id_column
178
     * as column name.
179
     *
180
     * @param   string  $id
181
     * @param   string  $table
182
     * @param   string  $id_column
183
     * @return  int|null
184
     */
185
    protected function get_int_id($id, $table, $id_column) {
186
        $res = $this->builder()
187
            ->select("id")
188
            ->from($table)
189
            ->where($this->builder()->expr()->andX
190
                ( "$id_column = ?"
191
                ))
192
            ->setParameter(0, $id)
193
            ->execute()
194
            ->fetch();
195
        if ($res) {
196
            return (int)$res["id"];
197
        }
198
        else {
199
            return null;
200
        }
201
    }
202
203
    // Naming
204
205
    public function name_table() {
206
        return "names";
207
    }
208
209 View Code Duplication
    public function init_name_table(S\Schema $schema) {
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
        $name_table = $schema->createTable($this->name_table());
211
        $name_table->addColumn
212
            ("id", "integer"
213
            , array("notnull" => true, "unsigned" => true, "autoincrement" => true)
214
            );
215
        $name_table->addColumn
216
            ( "name", "string"
217
            , array("notnull" => true)
218
            );
219
        // TODO: insert namespace column here
220
        $name_table->addColumn
221
            ( "type", "integer"
222
            , array("notnull" => true, "unsigned" => true)
223
            );
224
        $name_table->setPrimaryKey(array("id"));
225
        $name_table->addUniqueIndex(array("name"));
226
        return $name_table;
227
    }
228
229
    public function file_table() {
230
        return "files";
231
    }
232
233
    public function init_file_table(S\Schema $schema) {
234
        $file_table = $schema->createTable($this->file_table());
235
        $file_table->addColumn
236
            ("id", "integer"
237
            , array("notnull" => true, "unsigned" => true, "autoincrement" => true)
238
            );
239
        $file_table->addColumn
240
            ( "path", "string"
241
            , array("notnull" => true)
242
            );
243
        $file_table->setPrimaryKey(array("id"));
244
        return $file_table;
245
    }
246
247
    public function source_table() {
248
        return "source";
249
    }
250
251 View Code Duplication
    public function init_source_table(S\Schema $schema, S\Table $file_table) {
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...
252
        $source_table = $schema->createTable($this->source_table());
253
        $source_table->addColumn
254
            ( "file", "integer"
255
            , array("notnull" => true)
256
            );
257
        $source_table->addColumn
258
            ( "line", "integer"
259
            , array("notnull" => true, "unsigned" => true)
260
            );
261
        $source_table->addColumn
262
            ( "source", "string"
263
            , array("notnull" => true)
264
            );
265
        $source_table->setPrimaryKey(array("file", "line"));
266
        $source_table->addForeignKeyConstraint
267
            ( $file_table
268
            , array("file")
269
            , array("id")
270
            );
271
        return $source_table;
272
    }
273
274
    public function definition_table() {
275
        return "definitions";
276
    }
277
278 View Code Duplication
    public function init_definition_table(S\Schema $schema, S\Table $name_table, S\Table $source_table) {
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...
279
        $definition_table = $schema->createTable($this->definition_table());
280
        $definition_table->addColumn
281
            ("id", "integer"
282
            , array("notnull" => true, "unsigned" => true, "autoincrement" => true)
283
            );
284
        $definition_table->addColumn
285
            ( "name", "integer"
286
            , array("notnull" => true)
287
            );
288
        $definition_table->addColumn
289
            ( "file", "integer"
290
            , array("notnull" => true)
291
            );
292
        $definition_table->addColumn
293
            ( "start_line", "integer"
294
            , array("notnull" => true)
295
            );
296
        $definition_table->addColumn
297
            ( "end_line", "integer"
298
            , array("notnull" => true)
299
            );
300
        $definition_table->setPrimaryKey(array("id"));
301
        $definition_table->addForeignKeyConstraint
302
            ( $name_table
303
            , array("name")
304
            , array("id")
305
            );
306
        $definition_table->addForeignKeyConstraint
307
            ( $source_table
308
            , array("file", "start_line")
309
            , array("file", "line")
310
            );
311
        $definition_table->addForeignKeyConstraint
312
            ( $source_table
313
            , array("file", "end_line")
314
            , array("file", "line")
315
            );
316
        return $definition_table;
317
    }
318
319
    public function method_info_table() {
320
        return "method_info";
321
    }
322
323
    public function init_method_table(S\Schema $schema, S\Table $name_table, S\Table $definition_table) {
324
        $method_info_table = $schema->createTable($this->method_info_table());
325
        $method_info_table->addColumn
326
            ( "name", "integer"
327
            , array("notnull" => true)
328
            );
329
        $method_info_table->addColumn
330
            ( "class", "integer"
331
            , array("notnull" => true)
332
            );
333
        $method_info_table->addColumn
334
            ( "definition", "string"
335
            , array("notnull" => true)
336
            );
337
        $method_info_table->setPrimaryKey(array("name", "class"));
338
        $method_info_table->addForeignKeyConstraint
339
            ( $name_table
340
            , array("name")
341
            , array("id")
342
            );
343
        $method_info_table->addForeignKeyConstraint
344
            ( $name_table
345
            , array("class")
346
            , array("id")
347
            );
348
        $method_info_table->addForeignKeyConstraint
349
            ( $definition_table
350
            , array("definition")
351
            , array("id")
352
            );
353
        return $method_info_table;
354
    }
355
356
    public function relation_table() {
357
        return "relations";
358
    }
359
360 View Code Duplication
    public function init_relation_table(S\Schema $schema, S\Table $name_table, S\Table $source_table) {
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...
361
        $relation_table = $schema->createTable($this->relation_table());
362
        $relation_table->addColumn
363
            ("id", "integer"
364
            , array("notnull" => true, "unsigned" => true, "autoincrement" => true)
365
            );
366
        $relation_table->addColumn
367
            ( "name_left", "integer"
368
            , array("notnull" => true)
369
            );
370
        $relation_table->addColumn
371
            ( "name_right", "integer"
372
            , array("notnull" => true)
373
            );
374
        $relation_table->addColumn
375
            ( "which", "string"
376
            , array("notnull" => true)
377
            );
378
        $relation_table->addColumn
379
            ( "file", "integer"
380
            , array("notnull" => true)
381
            );
382
        $relation_table->addColumn
383
            ( "line", "integer"
384
            , array("notnull" => true)
385
            );
386
        $relation_table->setPrimaryKey(array("id"));
387
        $relation_table->addForeignKeyConstraint
388
            ( $name_table
389
            , array("name_left")
390
            , array("id")
391
            );
392
        $relation_table->addForeignKeyConstraint
393
            ( $name_table
394
            , array("name_right")
395
            , array("id")
396
            );
397
        $relation_table->addForeignKeyConstraint
398
            ( $source_table
399
            , array("file", "line")
400
            , array("file", "line")
401
            );
402
        return $relation_table;
403
    }
404
405
    // Creation of database.
406
407
    public function init_database_schema() {
408
        $schema = new S\Schema();
409
410
        $name_table = $this->init_name_table($schema);
411
        $file_table = $this->init_file_table($schema);
412
        $source_table = $this->init_source_table($schema, $file_table);
413
        $definition_table = $this->init_definition_table($schema, $name_table, $source_table);
414
        $this->init_method_table($schema, $name_table, $definition_table);
415
        $this->init_relation_table($schema, $name_table, $source_table);
416
417
        $sync = new SingleDatabaseSynchronizer($this->connection);
418
        $sync->createSchema($schema);
419
    }
420
}
421