Passed
Push — main ( 73aced...57fc6e )
by Pranjal
03:22
created

Database::select()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
/*
3
 * This file is part of the Scrawler package.
4
 *
5
 * (c) Pranjal Pandey <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
declare(strict_types=1);
12
13
namespace Scrawler\Arca;
14
15
use Doctrine\DBAL\Connection;
16
use Doctrine\DBAL\Types\Type;
17
use Dunglas\DoctrineJsonOdm\Serializer;
18
use Dunglas\DoctrineJsonOdm\Type\JsonDocumentType;
19
use Scrawler\Arca\Manager\ModelManager;
20
use Scrawler\Arca\Manager\RecordManager;
21
use Scrawler\Arca\Manager\WriteManager;
22
use Symfony\Component\Serializer\Encoder\JsonEncoder;
23
use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer;
24
use Symfony\Component\Serializer\Normalizer\BackedEnumNormalizer;
25
use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
26
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
27
use Symfony\Component\Serializer\Normalizer\UidNormalizer;
28
29
/**
30
 * Class that manages all interaction with database.
31
 */
32
final class Database
33
{
34
    /**
35
     * Create a new Database instance.
36
     */
37
    public function __construct(
38
        private readonly Connection $connection,
39
        private readonly RecordManager $recordManager,
40
        private readonly WriteManager $writeManager,
41
        private readonly ModelManager $modelManager,
42
        private readonly Config $config,
43
    ) {
44
        $this->registerJsonDocumentType();
45
    }
46
47
    /**
48
     * Executes an SQL query and returns the number of row affected.
49
     *
50
     * @param array<mixed> $params
51
     *
52
     * @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...
53
     */
54
    public function exec(string $sql, array $params = []): int|string
55
    {
56
        return $this->connection->executeStatement($sql, $params);
57
    }
58
59
    /**
60
     * Returns array of data from SQL select statement.
61
     *
62
     * @param array<mixed> $params
63
     *
64
     * @return array<int,array<string,mixed>>
65
     */
66
    public function getAll(string $sql, array $params = []): array
67
    {
68
        return $this->connection->executeQuery($sql, $params)->fetchAllAssociative();
69
    }
70
71
    /**
72
     * Creates model from name.
73
     */
74
    public function create(string $name): Model
75
    {
76
        return $this->modelManager->create($name);
77
    }
78
79
    /**
80
     * Save record to database.
81
     */
82
    public function save(Model $model): mixed
83
    {
84
        return $this->writeManager->save($model);
85
    }
86
87
    /**
88
     * Delete record from database.
89
     */
90
    public function delete(Model $model): mixed
91
    {
92
        return $this->recordManager->delete($model);
93
    }
94
95
    /**
96
     * Get collection of all records from table.
97
     */
98
    public function get(string $table): Collection
99
    {
100
        return $this->recordManager->getAll($table);
101
    }
102
103
    /**
104
     * Get single record.
105
     */
106
    public function getOne(string $table, mixed $id): ?Model
107
    {
108
        return $this->recordManager->getById($table, $id);
109
    }
110
111
    /**
112
     * Returns QueryBuilder to build query for finding data
113
     * Eg: db()->find('user')->where('active = 1')->get();.
114
     */
115
    public function find(string $name): QueryBuilder
116
    {
117
        return $this->recordManager->find($name);
118
    }
119
120
    /**
121
     * Returns QueryBuilder to build query for finding data
122
     * Eg: db()->select('*')->from('user')->where('active = 1')->get();.
123
     */
124
    public function select(string $expression): QueryBuilder
125
    {
126
        return $this->recordManager->select($expression);
127
    }
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
            // @phpstan-ignore-next-line
195
            Type::getType('json_document')->setSerializer(
0 ignored issues
show
Bug introduced by
The method setSerializer() does not exist on Doctrine\DBAL\Types\Type. It seems like you code against a sub-type of Doctrine\DBAL\Types\Type such as Dunglas\DoctrineJsonOdm\Type\JsonDocumentType. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

195
            Type::getType('json_document')->/** @scrutinizer ignore-call */ setSerializer(
Loading history...
196
                new Serializer([new BackedEnumNormalizer(), new UidNormalizer(), new DateTimeNormalizer(), new ArrayDenormalizer(), new ObjectNormalizer()], [new JsonEncoder()])
197
            );
198
        }
199
        // @codeCoverageIgnoreEnd
200
    }
201
}
202