Passed
Push — main ( 93d445...fd50fd )
by Pranjal
02:44 queued 14s
created

Database::getTableManager()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

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