|
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 licence 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\Connection; |
|
19
|
|
|
use Doctrine\DBAL\Schema; |
|
20
|
|
|
use Doctrine\DBAL\Types\Type; |
|
21
|
|
|
use Doctrine\DBAL\Schema\Synchronizer\SingleDatabaseSynchronizer; |
|
22
|
|
|
|
|
23
|
|
|
class DB implements Insert, Query { |
|
24
|
|
|
use CachesReferences; |
|
25
|
|
|
use CompilesVars; |
|
26
|
|
|
|
|
27
|
|
|
/** |
|
28
|
|
|
* @var Connection |
|
29
|
|
|
*/ |
|
30
|
|
|
protected $connection; |
|
31
|
|
|
|
|
32
|
52 |
|
public function __construct(Connection $connection) { |
|
33
|
52 |
|
$this->connection = $connection; |
|
34
|
52 |
|
} |
|
35
|
|
|
|
|
36
|
|
|
/** |
|
37
|
|
|
* @return \Doctrine\DBAL\Query\Builder |
|
38
|
|
|
*/ |
|
39
|
52 |
|
public function builder() { |
|
40
|
52 |
|
return $this->connection->createQueryBuilder(); |
|
41
|
|
|
} |
|
42
|
|
|
|
|
43
|
|
|
// Implementation of Insert interface. |
|
44
|
|
|
|
|
45
|
|
|
/** |
|
46
|
|
|
* @inheritdoc |
|
47
|
|
|
*/ |
|
48
|
51 |
View Code Duplication |
public function entity($type, $name, $file, $start_line, $end_line, $source) { |
|
|
|
|
|
|
49
|
51 |
|
assert('\\Lechimp\\Dicto\\Variables\\Variable::is_type($type)'); |
|
50
|
51 |
|
assert('is_string($name)'); |
|
51
|
51 |
|
assert('is_string($file)'); |
|
52
|
51 |
|
assert('is_int($start_line)'); |
|
53
|
51 |
|
assert('is_int($end_line)'); |
|
54
|
51 |
|
assert('is_string($source)'); |
|
55
|
51 |
|
$this->builder() |
|
56
|
51 |
|
->insert($this->entity_table()) |
|
57
|
51 |
|
->values(array |
|
58
|
|
|
( "type" => "?" |
|
59
|
51 |
|
, "name" => "?" |
|
60
|
51 |
|
, "file" => "?" |
|
61
|
51 |
|
, "start_line" => "?" |
|
62
|
51 |
|
, "end_line" => "?" |
|
63
|
51 |
|
, "source" => "?" |
|
64
|
51 |
|
)) |
|
65
|
51 |
|
->setParameter(0, $type) |
|
66
|
51 |
|
->setParameter(1, $name) |
|
67
|
51 |
|
->setParameter(2, $file) |
|
68
|
51 |
|
->setParameter(3, $start_line) |
|
69
|
51 |
|
->setParameter(4, $end_line) |
|
70
|
51 |
|
->setParameter(5, $source) |
|
71
|
51 |
|
->execute(); |
|
72
|
51 |
|
return (int)$this->connection->lastInsertId(); |
|
73
|
|
|
} |
|
74
|
|
|
|
|
75
|
|
|
/** |
|
76
|
|
|
* @inheritdoc |
|
77
|
|
|
*/ |
|
78
|
40 |
|
public function reference($type, $name, $file, $line) { |
|
79
|
40 |
|
assert('\\Lechimp\\Dicto\\Variables\\Variable::is_type($type)'); |
|
80
|
40 |
|
assert('is_string($name)'); |
|
81
|
40 |
|
assert('is_string($file)'); |
|
82
|
40 |
|
assert('is_int($line)'); |
|
83
|
40 |
|
$this->builder() |
|
84
|
40 |
|
->insert($this->reference_table()) |
|
85
|
40 |
|
->values(array |
|
86
|
|
|
( "type" => "?" |
|
87
|
40 |
|
, "name" => "?" |
|
88
|
40 |
|
, "file" => "?" |
|
89
|
40 |
|
, "line" => "?" |
|
90
|
40 |
|
)) |
|
91
|
40 |
|
->setParameter(0, $type) |
|
92
|
40 |
|
->setParameter(1, $name) |
|
93
|
40 |
|
->setParameter(2, $file) |
|
94
|
40 |
|
->setParameter(3, $line) |
|
95
|
40 |
|
->execute(); |
|
96
|
40 |
|
return (int)$this->connection->lastInsertId(); |
|
97
|
|
|
} |
|
98
|
|
|
|
|
99
|
|
|
/** |
|
100
|
|
|
* @inheritdoc |
|
101
|
|
|
*/ |
|
102
|
30 |
View Code Duplication |
public function relation($name, $entity_id, $reference_id, $file, $line, $source_line) { |
|
|
|
|
|
|
103
|
30 |
|
assert('is_string($name)'); |
|
104
|
30 |
|
assert('is_int($entity_id)'); |
|
105
|
30 |
|
assert('is_int($reference_id)'); |
|
106
|
30 |
|
assert('is_string($file)'); |
|
107
|
30 |
|
assert('is_int($line)'); |
|
108
|
30 |
|
assert('is_string($source_line)'); |
|
109
|
30 |
|
$this->builder() |
|
110
|
30 |
|
->insert($this->relations_table()) |
|
111
|
30 |
|
->values(array |
|
112
|
|
|
( "name" => "?" |
|
113
|
30 |
|
, "entity_id" => "?" |
|
114
|
30 |
|
, "reference_id" => "?" |
|
115
|
30 |
|
, "file" => "?" |
|
116
|
30 |
|
, "line" => "?" |
|
117
|
30 |
|
, "source_line" => "?" |
|
118
|
30 |
|
)) |
|
119
|
30 |
|
->setParameter(0, $name) |
|
120
|
30 |
|
->setParameter(1, $entity_id) |
|
121
|
30 |
|
->setParameter(2, $reference_id) |
|
122
|
30 |
|
->setParameter(3, $file) |
|
123
|
30 |
|
->setParameter(4, $line) |
|
124
|
30 |
|
->setParameter(5, $source_line) |
|
125
|
30 |
|
->execute(); |
|
126
|
30 |
|
} |
|
127
|
|
|
|
|
128
|
|
|
// Naming |
|
129
|
|
|
|
|
130
|
52 |
|
public function entity_table() { |
|
131
|
52 |
|
return "entities"; |
|
132
|
|
|
} |
|
133
|
|
|
|
|
134
|
52 |
|
public function reference_table() { |
|
135
|
52 |
|
return "refs"; |
|
136
|
|
|
} |
|
137
|
|
|
|
|
138
|
52 |
|
public function relations_table() { |
|
139
|
52 |
|
return "relations"; |
|
140
|
|
|
} |
|
141
|
|
|
|
|
142
|
|
|
/** |
|
143
|
|
|
* Initialize REGEXP for sqlite. |
|
144
|
|
|
*/ |
|
145
|
47 |
|
public function init_sqlite_regexp() { |
|
146
|
47 |
|
$pdo = $this->connection->getWrappedConnection(); |
|
147
|
47 |
|
if (!($pdo instanceof \PDO)) { |
|
148
|
|
|
throw new \RuntimeException( |
|
149
|
|
|
"Expected wrapped connection to be PDO-object."); |
|
150
|
|
|
} |
|
151
|
47 |
|
$pdo->sqliteCreateFunction("regexp", function($pattern, $data) { |
|
152
|
24 |
|
return preg_match("%$pattern%", $data) > 0; |
|
153
|
47 |
|
}); |
|
154
|
47 |
|
} |
|
155
|
|
|
|
|
156
|
|
|
// Creation of database. |
|
157
|
|
|
|
|
158
|
47 |
|
public function maybe_init_database_schema() { |
|
159
|
47 |
|
$res = $this->builder() |
|
160
|
47 |
|
->select("COUNT(*)") |
|
161
|
47 |
|
->from("sqlite_master") |
|
162
|
47 |
|
->where("type = 'table'") |
|
163
|
47 |
|
->execute() |
|
164
|
47 |
|
->fetchColumn(); |
|
165
|
47 |
|
if ($res == 0) { |
|
166
|
47 |
|
$this->init_database_schema(); |
|
167
|
47 |
|
} |
|
168
|
47 |
|
} |
|
169
|
|
|
|
|
170
|
52 |
|
public function init_database_schema() { |
|
171
|
52 |
|
$schema = new Schema\Schema(); |
|
172
|
|
|
|
|
173
|
52 |
|
$entity_table = $schema->createTable($this->entity_table()); |
|
174
|
52 |
|
$entity_table->addColumn |
|
175
|
52 |
|
("id", "integer" |
|
176
|
52 |
|
, array("notnull" => true, "unsigned" => true, "autoincrement" => true) |
|
177
|
52 |
|
); |
|
178
|
52 |
|
$entity_table->addColumn |
|
179
|
52 |
|
("type", "string" |
|
180
|
52 |
|
, array("notnull" => true) |
|
181
|
52 |
|
); |
|
182
|
52 |
|
$entity_table->addColumn |
|
183
|
52 |
|
("name", "string" |
|
184
|
52 |
|
, array("notnull" => true) |
|
185
|
52 |
|
); |
|
186
|
52 |
|
$entity_table->addColumn |
|
187
|
52 |
|
("file", "string" |
|
188
|
52 |
|
, array("notnull" => true) |
|
189
|
52 |
|
); |
|
190
|
52 |
|
$entity_table->addColumn |
|
191
|
52 |
|
("start_line", "integer" |
|
192
|
52 |
|
, array("notnull" => true, "unsigned" => true) |
|
193
|
52 |
|
); |
|
194
|
52 |
|
$entity_table->addColumn |
|
195
|
52 |
|
("end_line", "integer" |
|
196
|
52 |
|
, array("notnull" => true, "unsigned" => true) |
|
197
|
52 |
|
); |
|
198
|
52 |
|
$entity_table->addColumn |
|
199
|
52 |
|
("source", "text" |
|
200
|
52 |
|
, array("notnull" => true) |
|
201
|
52 |
|
); |
|
202
|
52 |
|
$entity_table->setPrimaryKey(array("id")); |
|
203
|
|
|
|
|
204
|
52 |
|
$reference_table = $schema->createTable($this->reference_table()); |
|
205
|
52 |
|
$reference_table->addColumn |
|
206
|
52 |
|
( "id", "integer" |
|
207
|
52 |
|
, array("notnull" => true, "unsigned" => true, "autoincrement" => true) |
|
208
|
52 |
|
); |
|
209
|
52 |
|
$reference_table->addColumn |
|
210
|
52 |
|
("type", "string" |
|
211
|
52 |
|
, array("notnull" => true) |
|
212
|
52 |
|
); |
|
213
|
52 |
|
$reference_table->addColumn |
|
214
|
52 |
|
("name", "string" |
|
215
|
52 |
|
, array("notnull" => true) |
|
216
|
52 |
|
); |
|
217
|
52 |
|
$reference_table->addColumn |
|
218
|
52 |
|
("file", "string" |
|
219
|
52 |
|
, array("notnull" => true) |
|
220
|
52 |
|
); |
|
221
|
52 |
|
$reference_table->addColumn |
|
222
|
52 |
|
("line", "integer" |
|
223
|
52 |
|
, array("notnull" => true, "unsigned" => true) |
|
224
|
52 |
|
); |
|
225
|
52 |
|
$reference_table->setPrimaryKey(array("id")); |
|
226
|
|
|
|
|
227
|
52 |
|
$relations_table = $schema->createTable($this->relations_table()); |
|
228
|
52 |
|
$relations_table->addColumn |
|
229
|
52 |
|
("name", "string" |
|
230
|
52 |
|
, array("notnull" => true) |
|
231
|
52 |
|
); |
|
232
|
52 |
|
$relations_table->addColumn |
|
233
|
52 |
|
( "entity_id", "integer" |
|
234
|
52 |
|
, array("notnull" => true, "unsigned" => true) |
|
235
|
52 |
|
); |
|
236
|
52 |
|
$relations_table->addColumn |
|
237
|
52 |
|
( "reference_id", "integer" |
|
238
|
52 |
|
, array("notnull" => true, "unsigned" => true) |
|
239
|
52 |
|
); |
|
240
|
52 |
|
$relations_table->addColumn |
|
241
|
52 |
|
("file", "string" |
|
242
|
52 |
|
, array("notnull" => true) |
|
243
|
52 |
|
); |
|
244
|
52 |
|
$relations_table->addColumn |
|
245
|
52 |
|
("line", "integer" |
|
246
|
52 |
|
, array("notnull" => true, "unsigned" => true) |
|
247
|
52 |
|
); |
|
248
|
52 |
|
$relations_table->addColumn |
|
249
|
52 |
|
("source_line", "text" |
|
250
|
52 |
|
, array("notnull" => true) |
|
251
|
52 |
|
); |
|
252
|
52 |
|
$relations_table->addForeignKeyConstraint |
|
253
|
52 |
|
( $entity_table |
|
254
|
52 |
|
, array("entity_id") |
|
255
|
52 |
|
, array("id") |
|
256
|
52 |
|
); |
|
257
|
52 |
|
$relations_table->addForeignKeyConstraint |
|
258
|
52 |
|
( $reference_table |
|
259
|
52 |
|
, array("reference_id") |
|
260
|
52 |
|
, array("id") |
|
261
|
52 |
|
); |
|
262
|
|
|
|
|
263
|
52 |
|
$sync = new SingleDatabaseSynchronizer($this->connection); |
|
264
|
52 |
|
$sync->createSchema($schema); |
|
265
|
52 |
|
} |
|
266
|
|
|
} |
|
267
|
|
|
|
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.