RecordManager::createQueryBuilder()   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 0
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
namespace Scrawler\Arca\Manager;
13
14
use Doctrine\DBAL\Connection;
15
use Ramsey\Uuid\Uuid;
16
use Scrawler\Arca\Collection;
17
use Scrawler\Arca\Config;
18
use Scrawler\Arca\Model;
19
use Scrawler\Arca\QueryBuilder;
20
21
/**
22
 * Class responsible for manging single records.
23
 */
24
final class RecordManager
25
{
26
    private const ID_COLUMN = 'id';
27
    private const DEFAULT_ALIAS = 't';
28
    private const ALL_COLUMNS = '*';
29
30
    /**
31
     * Create RecordManager.
32
     */
33
    public function __construct(
34
        private readonly Connection $connection,
35
        private readonly ModelManager $modelManager,
36
        private readonly Config $config,
37
    ) {
38
    }
39
40
    /**
41
     * Execute operations within a transaction.
42
     *
43
     * @template T
44
     *
45
     * @param callable(): T $callback
46
     *
47
     * @return T
48
     *
49
     * @throws \Exception
50
     */
51
    private function executeInTransaction(callable $callback): mixed
52
    {
53
        if (!$this->connection->isTransactionActive()) {
54
            $this->connection->beginTransaction();
55
            try {
56
                $result = $callback();
57
                $this->connection->commit();
58
59
                return $result;
60
            } catch (\Exception $e) {
61
                $this->connection->rollBack();
62
                throw $e;
63
            }
64
        }
65
66
        // If already in transaction, just execute the callback
67
        return $callback();
68
    }
69
70
    /**
71
     * Create a new record.
72
     */
73
    public function insert(Model $model): mixed
74
    {
75
        return $this->executeInTransaction(function () use ($model) {
76
            if ($this->config->isUsingUUID()) {
77
                $model->set(self::ID_COLUMN, Uuid::uuid4()->toString());
78
            }
79
80
            $this->connection->insert(
81
                $model->getName(),
82
                $model->getSelfProperties()
83
            );
84
85
            if ($this->config->isUsingUUID()) {
86
                return $model->get(self::ID_COLUMN);
87
            }
88
89
            return (int) $this->connection->lastInsertId();
90
        });
91
    }
92
93
    /**
94
     * Update a record.
95
     */
96
    public function update(Model $model): mixed
97
    {
98
        return $this->executeInTransaction(function () use ($model) {
99
            $this->connection->update(
100
                $model->getName(),
101
                $model->getSelfProperties(),
102
                [self::ID_COLUMN => $model->getId()]
103
            );
104
105
            return $model->getId();
106
        });
107
    }
108
109
    /**
110
     * Delete a record.
111
     */
112
    public function delete(Model $model): mixed
113
    {
114
        return $this->executeInTransaction(function () use ($model) {
115
            $this->connection->delete(
116
                $model->getName(),
117
                [self::ID_COLUMN => $model->getId()]
118
            );
119
120
            return $model->getId();
121
        });
122
    }
123
124
    /**
125
     * Get single record by id.
126
     */
127
    public function getById(string $table, mixed $id): ?Model
128
    {
129
        return $this->executeInTransaction(function () use ($table, $id) {
130
            return $this->createQueryBuilder()
131
                ->select(self::ALL_COLUMNS)
132
                ->from($table, self::DEFAULT_ALIAS)
133
                ->where(self::DEFAULT_ALIAS.'.'.self::ID_COLUMN.' = ?')
134
                ->setParameter(0, $id)
135
                ->first();
136
        });
137
    }
138
139
    /**
140
     * Get all records.
141
     */
142
    public function getAll(string $tableName): Collection
143
    {
144
        return $this->executeInTransaction(function () use ($tableName) {
145
            return $this->createQueryBuilder()
146
                ->select(self::ALL_COLUMNS)
147
                ->from($tableName, self::DEFAULT_ALIAS)
148
                ->get();
149
        });
150
    }
151
152
    /**
153
     * Create a new QueryBuilder instance.
154
     */
155
    private function createQueryBuilder(): QueryBuilder
156
    {
157
        return new QueryBuilder($this->connection, $this->modelManager);
158
    }
159
160
    /**
161
     * Get query builder from db.
162
     */
163
    public function find(string $name): QueryBuilder
164
    {
165
        return $this->createQueryBuilder()
166
            ->select(self::ALL_COLUMNS)
167
            ->from($name, self::DEFAULT_ALIAS);
168
    }
169
170
    /**
171
     * Get query builder from db.
172
     */
173
    public function select(string $expression): QueryBuilder
174
    {
175
        return $this->createQueryBuilder()->select($expression);
176
    }
177
}
178