Passed
Push — master ( 27e097...2572c0 )
by Maxim
04:32
created

AbstractEntityRepositoryDb::findOne()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

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

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

190
                    : /** @scrutinizer ignore-call */ \unserialize($row[$field], ['allowed_classes' => true]);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
191
            }
192
        }
193
    }
194
}
195