Completed
Push — master ( 953783...055045 )
by Dominik
02:02
created

AbstractDoctrineRepository::update()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 6

Duplication

Lines 11
Ratio 100 %

Importance

Changes 0
Metric Value
dl 11
loc 11
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 6
nc 1
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Chubbyphp\Model;
6
7
use Chubbyphp\Model\Cache\ModelCacheInterface;
8
use Chubbyphp\Model\Cache\NullModelCache;
9
use Doctrine\DBAL\Connection;
10
use Doctrine\DBAL\Query\QueryBuilder;
11
use Psr\Log\LoggerInterface;
12
use Psr\Log\NullLogger;
13
14
abstract class AbstractDoctrineRepository implements RepositoryInterface
15
{
16
    /**
17
     * @var Connection
18
     */
19
    private $connection;
20
21
    /**
22
     * @var ModelCacheInterface
23
     */
24
    private $cache;
25
26
    /**
27
     * @var LoggerInterface
28
     */
29
    private $logger;
30
31
    /**
32
     * @param Connection               $connection
33
     * @param ModelCacheInterface|null $cache
34
     * @param LoggerInterface|null     $logger
35
     */
36
    public function __construct(
37
        Connection $connection,
38
        ModelCacheInterface $cache = null,
39
        LoggerInterface $logger = null
40
    ) {
41
        $this->connection = $connection;
42
        $this->cache = $cache ?? new NullModelCache();
43
        $this->logger = $logger ?? new NullLogger();
44
    }
45
46
    /**
47
     * @param string $id
48
     *
49
     * @return ModelInterface|null
50
     */
51
    public function find(string $id)
52
    {
53
        /** @var ModelInterface $modelClass */
54
        $modelClass = $this->getModelClass();
55
56
        $this->logger->info('model: find model {model} with id {id}', ['model' => $modelClass, 'id' => $id]);
57
58
        if ($this->cache->has($id)) {
59
            return $this->cache->get($id);
60
        }
61
62
        $qb = $this->connection->createQueryBuilder();
63
        $qb->select('*')->from($this->getTable())->where($qb->expr()->eq('id', ':id'))->setParameter('id', $id);
64
65
        $row = $qb->execute()->fetch(\PDO::FETCH_ASSOC);
66 View Code Duplication
        if (false === $row) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
67
            $this->logger->warning(
68
                'model: model {model} with id {id} not found',
69
                ['model' => $modelClass, 'id' => $id]
70
            );
71
72
            return null;
73
        }
74
75
        $model = $modelClass::fromRow($row);
76
77
        $this->cache->set($model);
78
79
        return $model;
80
    }
81
82
    /**
83
     * @param array $criteria
84
     *
85
     * @return null|ModelInterface
86
     */
87
    public function findOneBy(array $criteria = [])
88
    {
89
        /** @var ModelInterface $modelClass */
90
        $modelClass = $this->getModelClass();
91
92
        $this->logger->info(
93
            'model: find model {model} with criteria {criteria}',
94
            ['model' => $modelClass, 'criteria' => $criteria]
95
        );
96
97
        $qb = $this->getFindByQueryBuilder($criteria)->setMaxResults(1);
98
99
        $row = $qb->execute()->fetch(\PDO::FETCH_ASSOC);
100 View Code Duplication
        if (false === $row) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
101
            $this->logger->warning(
102
                'model: model {model} with criteria {criteria} not found',
103
                ['model' => $modelClass, 'criteria' => $criteria]
104
            );
105
106
            return null;
107
        }
108
109
        return $modelClass::fromRow($row);
110
    }
111
112
    /**
113
     * @param array $criteria
114
     *
115
     * @return ModelInterface[]|array
116
     */
117
    public function findBy(array $criteria = []): array
118
    {
119
        /** @var ModelInterface $modelClass */
120
        $modelClass = $this->getModelClass();
121
122
        $this->logger->info(
123
            'model: find model {model} with criteria {criteria}',
124
            ['model' => $modelClass, 'criteria' => $criteria]
125
        );
126
127
        $rows = $this->getFindByQueryBuilder($criteria)->execute()->fetchAll(\PDO::FETCH_ASSOC);
128
129
        if ([] === $rows) {
130
            return [];
131
        }
132
133
        $models = [];
134
        foreach ($rows as $row) {
135
            $models[] = $modelClass::fromRow($row);
136
        }
137
138
        return $models;
139
    }
140
141
    /**
142
     * @param array $criteria
143
     *
144
     * @return QueryBuilder
145
     */
146
    private function getFindByQueryBuilder(array $criteria = []): QueryBuilder
147
    {
148
        $qb = $this->connection->createQueryBuilder();
149
        $qb->select('*')->from($this->getTable());
150
151
        foreach ($criteria as $field => $value) {
152
            $qb->andWhere($qb->expr()->eq($field, ':'.$field));
153
            $qb->setParameter($field, $value);
154
        }
155
156
        return $qb;
157
    }
158
159
    /**
160
     * @param ModelInterface $model
161
     */
162 View Code Duplication
    public function insert(ModelInterface $model)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
163
    {
164
        $this->logger->info(
165
            'model: insert model {model} with id {id}',
166
            ['model' => get_class($model), 'id' => $model->getId()]
167
        );
168
169
        $this->connection->insert($this->getTable(), $model->toRow());
170
171
        $this->cache->set($model);
172
    }
173
174
    /**
175
     * @param ModelInterface $model
176
     */
177 View Code Duplication
    public function update(ModelInterface $model)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
178
    {
179
        $this->logger->info(
180
            'model: update model {model} with id {id}',
181
            ['model' => get_class($model), 'id' => $model->getId()]
182
        );
183
184
        $this->connection->update($this->getTable(), $model->toRow(), ['id' => $model->getId()]);
185
186
        $this->cache->set($model);
187
    }
188
189
    /**
190
     * @param ModelInterface $model
191
     */
192 View Code Duplication
    public function delete(ModelInterface $model)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
193
    {
194
        $this->logger->info(
195
            'model: delete model {model} with id {id}',
196
            ['model' => get_class($model), 'id' => $model->getId()]
197
        );
198
199
        $this->connection->delete($this->getTable(), ['id' => $model->getId()]);
200
201
        $this->cache->remove($model->getId());
202
    }
203
204
    /**
205
     * @return string
206
     */
207
    abstract protected function getTable(): string;
208
}
209