Database::find()   A
last analyzed

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
3
/*
4
 * This file is part of the Scrawler package.
5
 *
6
 * (c) Pranjal Pandey <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace Scrawler\Arca;
15
16
use Doctrine\DBAL\Connection;
17
use Doctrine\DBAL\Types\Type;
18
use Dunglas\DoctrineJsonOdm\Serializer;
19
use Dunglas\DoctrineJsonOdm\Type\JsonDocumentType;
20
use Scrawler\Arca\Manager\ModelManager;
21
use Scrawler\Arca\Manager\RecordManager;
22
use Scrawler\Arca\Manager\WriteManager;
23
use Symfony\Component\Serializer\Encoder\JsonEncoder;
24
use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer;
25
use Symfony\Component\Serializer\Normalizer\BackedEnumNormalizer;
26
use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
27
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
28
use Symfony\Component\Serializer\Normalizer\UidNormalizer;
29
30
/**
31
 * Class that manages all interaction with database.
32
 */
33
final class Database
34
{
35
    /**
36
     * Create a new Database instance.
37
     */
38
    public function __construct(
39
        private readonly Connection $connection,
40
        private readonly RecordManager $recordManager,
41
        private readonly WriteManager $writeManager,
42
        private readonly ModelManager $modelManager,
43
        private readonly Config $config,
44
    ) {
45
        $this->registerJsonDocumentType();
46
    }
47
48
    /**
49
     * Executes an SQL query and returns the number of row affected.
50
     *
51
     * @param array<mixed> $params
52
     *
53
     * @return int|numeric-string
0 ignored issues
show
Documentation Bug introduced by
The doc comment int|numeric-string at position 2 could not be parsed: Unknown type name 'numeric-string' at position 2 in int|numeric-string.
Loading history...
54
     */
55
    public function exec(string $sql, array $params = []): int|string
56
    {
57
        return $this->connection->executeStatement($sql, $params);
58
    }
59
60
    /**
61
     * Returns array of data from SQL select statement.
62
     *
63
     * @param array<mixed> $params
64
     *
65
     * @return array<int,array<string,mixed>>
66
     */
67
    public function getAll(string $sql, array $params = []): array
68
    {
69
        return $this->connection->executeQuery($sql, $params)->fetchAllAssociative();
70
    }
71
72
    /**
73
     * Creates model from name.
74
     */
75
    public function create(string $name): Model
76
    {
77
        return $this->modelManager->create($name);
78
    }
79
80
    /**
81
     * Save record to database.
82
     */
83
    public function save(Model $model): mixed
84
    {
85
        return $this->writeManager->save($model);
86
    }
87
88
    /**
89
     * Delete record from database.
90
     */
91
    public function delete(Model $model): mixed
92
    {
93
        return $this->recordManager->delete($model);
94
    }
95
96
    /**
97
     * Get collection of all records from table.
98
     */
99
    public function get(string $table): Collection
100
    {
101
        return $this->recordManager->getAll($table);
102
    }
103
104
    /**
105
     * Get single record.
106
     */
107
    public function getOne(string $table, mixed $id): ?Model
108
    {
109
        return $this->recordManager->getById($table, $id);
110
    }
111
112
    /**
113
     * Returns QueryBuilder to build query for finding data
114
     * Eg: db()->find('user')->where('active = 1')->get();.
115
     */
116
    public function find(string $name): QueryBuilder
117
    {
118
        return $this->recordManager->find($name);
119
    }
120
121
    /**
122
     * Returns QueryBuilder to build query for finding data
123
     * Eg: db()->select('*')->from('user')->where('active = 1')->get();.
124
     */
125
    public function select(string $expression): QueryBuilder
126
    {
127
        return $this->recordManager->select($expression);
128
    }
129
130
    /**
131
     * Freezes table for production.
132
     */
133
    public function freeze(): void
134
    {
135
        $this->config->setFrozen(true);
136
    }
137
138
    /**
139
     * Helper function to unfreeze table.
140
     */
141
    public function unfreeze(): void
142
    {
143
        $this->config->setFrozen(false);
144
    }
145
146
    /**
147
     * Checks if database is currently using uuid rather than id.
148
     */
149
    public function isUsingUUID(): bool
150
    {
151
        return $this->config->isUsingUUID();
152
    }
153
154
    /**
155
     * Returns the current connection.
156
     */
157
    public function getConnection(): Connection
158
    {
159
        return $this->connection;
160
    }
161
162
    /**
163
     * Check if tables exist.
164
     *
165
     * @param array<int,string> $tables
166
     */
167
    public function tablesExist(array $tables): bool
168
    {
169
        return $this->connection
170
            ->createSchemaManager()
171
            ->tablesExist($tables);
172
    }
173
174
    /**
175
     * Check if table exists.
176
     */
177
    public function tableExists(string $table): bool
178
    {
179
        return $this->connection
180
            ->createSchemaManager()
181
            ->tableExists($table);
182
    }
183
184
    /**
185
     * Register additional json_document type.
186
     * Note: storing and retrival of array is being tested
187
     * so ignoring this in coverage.
188
     */
189
    private function registerJsonDocumentType(): void
190
    {
191
        // @codeCoverageIgnoreStart
192
        if (!Type::hasType('json_document')) {
193
            Type::addType('json_document', JsonDocumentType::class);
194
            $jsonDocumentType = Type::getType('json_document');
195
            if ($jsonDocumentType instanceof JsonDocumentType) {
196
                $jsonDocumentType->setSerializer(
197
                    new Serializer([new BackedEnumNormalizer(), new UidNormalizer(), new DateTimeNormalizer(), new ArrayDenormalizer(), new ObjectNormalizer()], [new JsonEncoder()])
198
                );
199
            }
200
        }
201
        // @codeCoverageIgnoreEnd
202
    }
203
}
204