Completed
Push — master ( 1a5eaf...51a843 )
by Richard
05:35
created

DB::relation()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 16
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 1

Importance

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