Passed
Push — main ( 81fc9d...082349 )
by Pranjal
14:11
created

Database::createTables()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 3
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 5
rs 10
1
<?php
2
declare(strict_types=1);
3
4
namespace Scrawler\Arca;
5
use Scrawler\Arca\Manager\TableManager;
6
use Scrawler\Arca\Manager\RecordManager;
7
use Scrawler\Arca\Manager\ModelManager;
8
use \Doctrine\DBAL\DriverManager;
9
10
class Database
11
{
12
    public \Doctrine\DBAL\Connection $connection;
13
    public \Doctrine\DBAL\Platforms\AbstractPlatform $platform;
14
    public \Doctrine\DBAL\Schema\AbstractSchemaManager $manager;
15
    private TableManager $tableManager;
16
    private RecordManager $recordManager;
17
    private ModelManager $modelManager;
18
    private bool $isFroozen = false;
19
    private bool $useUUID = false;
20
21
    public function __construct(DriverManager $connection)
22
    {
23
        $this->connection = $connection;
24
        $this->platform = $this->connection->getDatabasePlatform();
25
        $this->manager = $this->connection->createSchemaManager();
26
        
27
    }
28
29
    public function setManagers(TableManager $tableManger, RecordManager $recordManager, ModelManager $modelManager){
30
        $this->tableManager = $tableManager;
31
        $this->recordManager = $recordManager;
32
        $this->modelManager = $modelManager;
33
34
    }
35
36
    /**
37
     * Executes an SQL query and returns the number of row affected
38
     *
39
     * @param string $sql
40
     * @param array $params
41
     * @return integer
42
     */
43
    public function exec(string $sql, array $params=array()): int
44
    {
45
        return  $this->connection->executeStatement($sql, $params);
46
    }
47
48
    /**
49
     * Returns array of data from SQL select statement
50
     *
51
     * @param string $sql
52
     * @param array $params
53
     * @return array
54
     */
55
    public function getAll(string $sql, array $params=[]): array
56
    {
57
        return  $this->connection->executeQuery($sql, $params)->fetchAllAssociative();
58
    }
59
60
    /**
61
     * Creates model from name
62
     *
63
     * @param string $name
64
     * @return \Scrawler\Arca\Model
65
     */
66
    public function create(string $name) : Model
67
    {
68
        return $this->modelManager->create($name)
69
    }
0 ignored issues
show
Bug introduced by
A parse error occurred: Syntax error, unexpected '}', expecting ';' on line 69 at column 4
Loading history...
70
71
    /**
72
     * Save model into database
73
     *
74
     * @param \Scrawler\Arca\Model $model
75
     * @return mixed returns int for id and string for uuid
76
     */
77
    public function save(\Scrawler\Arca\Model $model) : mixed
78
    {
79
        if ($model->hasForeign('oto')) {
80
            $this->saveForeignOto($model);
81
        }
82
        
83
        $this->createTables($model);
84
        $this->connection->beginTransaction();
85
86
        try {
87
            $id = $this->createRecords($model);
88
            $this->connection->commit();
89
        } catch (\Exception $e) {
90
            $this->connection->rollBack();
91
            throw $e;
92
        }
93
        
94
        if ($model->hasForeign('otm')) {
95
            $this->saveForeignOtm($model, $id);
96
        }
97
98
        if ($model->hasForeign('mtm')) {
99
            $this->saveForeignMtm($model, $id);
100
        }
101
102
        return $id;
103
    }
104
105
    private function createTables($model)
106
    {
107
        if (!$this->isFroozen) {
108
            $table = $this->tableManager->createTable($model);
109
            $this->tableManager->saveOrUpdateTable($model->getName(), $table);
110
        }
111
    }
112
113
    private function createRecords($model) : mixed
114
    {
115
        if ($model->isLoaded()) {
116
            return $this->recordManager->update($model);
117
        }
118
        
119
        return $this->recordManager->insert($model);
120
    }
121
122
    /**
123
     * Save One to One related model into database
124
     */
125
    private function saveForeignOto(\Scrawler\Arca\Model $model): void
126
    {
127
        foreach ($model->getForeignModels('oto') as $foreign) {
128
            $this->createTables($foreign);
129
        }
130
131
        $this->connection->beginTransaction();
132
        try {
133
            foreach ($model->getForeignModels('oto') as $foreign) {
134
                $id = $this->createRecords($foreign);
135
                $name = $foreign->getName().'_id';
136
                $model->$name = $id;
137
            }
138
            $this->connection->commit();
139
        } catch (\Exception $e) {
140
            $this->connection->rollBack();
141
            throw $e;
142
        }
143
    }
144
145
    /**
146
     * Save One to Many related model into database
147
     */
148
    private function saveForeignOtm(\Scrawler\Arca\Model $model, mixed $id): void
149
    {
150
        foreach ($model->getForeignModels('otm') as $foreigns) {
151
            foreach ($foreigns as $foreign) {
152
                $key = $model->getName().'_id';
153
                $foreign->$key = $id;
154
                $this->createTables($foreign);
155
            }
156
        }
157
        $this->connection->beginTransaction();
158
        try {
159
            foreach ($model->getForeignModels('otm') as $foreigns) {
160
                foreach ($foreigns as $foreign) {
161
                    $this->createRecords($foreign);
162
                }
163
            }
164
            $this->connection->commit();
165
        } catch (\Exception $e) {
166
            $this->connection->rollBack();
167
            throw $e;
168
        }
169
    }
170
171
    /**
172
     * Save Many to Many related model into database
173
     */
174
    private function saveForeignMtm(\Scrawler\Arca\Model $model, mixed $id): void
175
    {
176
        foreach ($model->getForeignModels('mtm') as $foreigns) {
177
            foreach ($foreigns as $foreign) {
178
                $model_id = $model->getName().'_id';
179
                $foreign_id = $foreign->getName().'_id';
180
                $relational_table = $this->create($model->getName().'_'.$foreign->getName());
181
                if ($this->isUsingUUID()) {
182
                    $relational_table->$model_id = "";
183
                    $relational_table->$foreign_id = "";
184
                } else {
185
                    $relational_table->$model_id = 0;
186
                    $relational_table->$foreign_id = 0;
187
                }
188
                $this->createTables($relational_table);
189
                $this->createTables($foreign);
190
            }
191
        }
192
        $this->connection->beginTransaction();
193
        try {
194
            foreach ($model->getForeignModels('mtm') as $foreigns) {
195
                foreach ($foreigns as $foreign) {
196
                    $rel_id = $this->createRecords($foreign);
197
                    $model_id = $model->getName().'_id';
198
                    $foreign_id = $foreign->getName().'_id';
199
                    $relational_table = $this->create($model->getName().'_'.$foreign->getName());
200
                    $relational_table->$model_id = $id;
201
                    $relational_table->$foreign_id = $rel_id;
202
                    $this->createRecords($relational_table);
203
                }
204
            }
205
            $this->connection->commit();
206
        } catch (\Exception $e) {
207
            $this->connection->rollBack();
208
            throw $e;
209
        }
210
    }
211
212
    public function getTableManager()
213
    {
214
        return $this->tableManager;
215
    }
216
217
    /**
218
     * Delete record from database
219
     *
220
     * @param \Scrawler\Arca\Model $model
221
     * @return mixed
222
     */
223
    public function delete(\Scrawler\Arca\Model $model) : mixed
224
    {
225
        return $this->recordManager->delete($model);
226
    }
227
228
    /**
229
     * Get single
230
     *
231
     * @param String $table
232
     * @param mixed|null $id
233
     * @return mixed
234
     */
235
    public function get(String $table, mixed $id=null) : mixed
236
    {
237
        if (is_null($id)) {
238
            return $this->recordManager->getAll($table);
239
        }
240
241
        $model = $this->create($table);
242
        return $this->recordManager->getById($model, $id);
243
    }
244
245
    /**
246
     * Returns QueryBuilder to build query for finding data
247
     * Eg: db()->find('user')->where('active = 1')->get();
248
     *
249
     * @param string $name
250
     * @return QueryBuilder
251
     */
252
    public function find(string $name) : QueryBuilder
253
    {
254
        return $this->recordManager->find($name);
255
    }
256
257
    public function freeze() : void
258
    {
259
        $this->isFroozen = true;
260
    }
261
262
    public function useUUID() : void
263
    {
264
        $this->useUUID = true;
265
    }
266
267
    public function useID() : void
268
    {
269
        $this->useUUID = false;
270
    }
271
272
    public function isUsingUUID() : bool
273
    {
274
        return $this->useUUID;
275
    }
276
}
277