AbstractEntityRepositoryDb::count()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace WebComplete\core\entity;
4
5
use Doctrine\DBAL\Connection;
6
use Doctrine\DBAL\Query\QueryBuilder;
7
use WebComplete\core\condition\ConditionDbParser;
8
use WebComplete\core\factory\EntityFactory;
9
use WebComplete\core\condition\Condition;
10
11
abstract class AbstractEntityRepositoryDb extends AbstractEntityRepository
12
{
13
    const SERIALIZE_STRATEGY_JSON = 1;
14
    const SERIALIZE_STRATEGY_PHP  = 2;
15
16
    protected $table;
17
    protected $serializeFields = [];
18
    protected $serializeStrategy = self::SERIALIZE_STRATEGY_JSON;
19
20
    /** @var Connection */
21
    protected $db;
22
23
    /**
24
     * @var ConditionDbParser
25
     */
26
    protected $conditionParser;
27
28
    /**
29
     * @param EntityFactory $factory
30
     * @param ConditionDbParser $conditionParser
31
     * @param Connection $db
32
     */
33
    public function __construct(
34
        EntityFactory $factory,
35
        ConditionDbParser $conditionParser,
36
        Connection $db
37
    ) {
38
        parent::__construct($factory);
39
        $this->db = $db;
40
        $this->conditionParser = $conditionParser;
41
    }
42
43
    /**
44
     * @return string
45
     */
46
    public function getTable(): string
47
    {
48
        return $this->table;
49
    }
50
51
    /**
52
     * @param \Closure $closure
53
     * @throws \Exception
54
     */
55
    public function transaction(\Closure $closure)
56
    {
57
        $this->db->transactional($closure);
58
    }
59
60
    /**
61
     * @param $id
62
     * @return AbstractEntity|null
63
     */
64
    public function findById($id)
65
    {
66
        return $this->findOne($this->createCondition(['t1.id' => $id]));
67
    }
68
69
    /**
70
     * @param Condition $condition
71
     * @return AbstractEntity|null
72
     */
73
    public function findOne(Condition $condition)
74
    {
75
        $result = null;
76
        $select = $this->selectQuery($condition);
77
        if ($row = $select->execute()->fetch()) {
78
            $result = $this->rowToEntity($row);
79
        }
80
81
        return $result;
82
    }
83
84
    /**
85
     * @param Condition $condition
86
     * @return AbstractEntity[]
87
     */
88
    public function findAll(Condition $condition = null): array
89
    {
90
        $result = [];
91
        $select = $this->selectQuery($condition);
92
        if ($rows = $select->execute()->fetchAll(\PDO::FETCH_ASSOC)) {
93
            foreach ($rows as $row) {
94
                $entity = $this->rowToEntity($row);
95
                $result[$entity->getId()] = $entity;
96
            }
97
        }
98
99
        return $result;
100
    }
101
102
    /**
103
     * @param Condition|null $condition
104
     * @return int
105
     */
106
    public function count(Condition $condition = null): int
107
    {
108
        $select = $this->selectQuery($condition);
109
        return $select->select(['t1.id'])->execute()->rowCount();
110
    }
111
112
    /**
113
     * @param AbstractEntity $item
114
     */
115
    public function save(AbstractEntity $item)
116
    {
117
        $data = $item->mapToArray();
118
        $this->beforeDataSave($data);
119
        $this->serializeFields($data);
120
        if ($id = $item->getId()) {
121
            $this->db->update($this->table, $data, ['t1.id' => $id]);
122
        } else {
123
            unset($data['id']);
124
            $this->db->insert($this->table, $data);
125
            $item->setId((int)$this->db->lastInsertId());
126
        }
127
    }
128
129
    /**
130
     * @param $id
131
     *
132
     * @throws \Doctrine\DBAL\Exception\InvalidArgumentException
133
     */
134
    public function delete($id)
135
    {
136
        $this->db->delete($this->table, ['t1.id' => $id]);
137
    }
138
139
    /**
140
     * @param Condition|null $condition
141
     */
142
    public function deleteAll(Condition $condition = null)
143
    {
144
        $query = $this->selectQuery($condition);
145
        $query->delete($this->table, 't1');
146
        $query->execute();
147
    }
148
149
    /**
150
     * @param string $field
151
     * @param string $key
152
     * @param Condition|null $condition
153
     *
154
     * @return array
155
     * @throws \Exception
156
     */
157
    public function getMap(string $field, string $key = 'id', Condition $condition = null): array
158
    {
159
        $result = [];
160
        $select = $this->selectQuery($condition);
161
        $select->select(['t1.' . $field, 't1.' . $key]);
162
        if ($rows = $select->execute()->fetchAll(\PDO::FETCH_ASSOC)) {
163
            foreach ($rows as $row) {
164
                $this->unserializeFields($row);
165
                $result[$row[$key]] = $row[$field];
166
            }
167
        }
168
169
        return $result;
170
    }
171
172
    /**
173
     * @param Condition|null $condition
174
     * @return QueryBuilder
175
     */
176
    protected function selectQuery(Condition $condition = null): QueryBuilder
177
    {
178
        $queryBuilder = $this->db->createQueryBuilder();
179
        $queryBuilder->select(['t1.*'])->from($this->table, 't1');
180
        $this->conditionParser->parse($queryBuilder, $condition);
181
        return $queryBuilder;
182
    }
183
184
    /**
185
     * Adjust data before save
186
     * @param $data
187
     */
188
    protected function beforeDataSave(&$data)
0 ignored issues
show
Unused Code introduced by
The parameter $data is not used and could be removed. ( Ignorable by Annotation )

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

188
    protected function beforeDataSave(/** @scrutinizer ignore-unused */ &$data)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
189
    {
190
    }
191
192
    /**
193
     * @param $data
194
     *
195
     * @return AbstractEntity
196
     */
197
    private function rowToEntity($data): AbstractEntity
198
    {
199
        $this->unserializeFields($data);
200
        /** @var AbstractEntity $entity */
201
        $entity = $this->factory->create();
202
        $entity->mapFromArray($data);
203
        return $entity;
204
    }
205
206
    /**
207
     * @param $data
208
     */
209
    private function serializeFields(&$data)
210
    {
211
        foreach ($this->serializeFields as $field) {
212
            if (isset($data[$field])) {
213
                $data[$field] = $this->serializeStrategy === self::SERIALIZE_STRATEGY_JSON
214
                    ? \json_encode($data[$field])
215
                    : \serialize($data[$field]);
216
            }
217
        }
218
    }
219
220
    /**
221
     * @param $row
222
     */
223
    private function unserializeFields(&$row)
224
    {
225
        foreach ($this->serializeFields as $field) {
226
            if (isset($row[$field])) {
227
                $row[$field] = $this->serializeStrategy === self::SERIALIZE_STRATEGY_JSON
228
                    ? \json_decode($row[$field], true)
229
                    : \unserialize($row[$field], ['allowed_classes' => true]);
230
            }
231
        }
232
    }
233
}
234