Passed
Push — main ( a04c10...ce0e6f )
by Pranjal
01:52
created

Database::find()   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 1
dl 0
loc 3
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;
0 ignored issues
show
Bug introduced by
The type \Doctrine\DBAL\DriverManager was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
9
use \Doctrine\DBAL\Connection;
0 ignored issues
show
Bug introduced by
The type \Doctrine\DBAL\Connection was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

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