Completed
Push — master ( 639c65...497f34 )
by Maxim
06:00
created

AbstractEntityRepositoryDb::transaction()   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
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
            $this->unserializeFields($row);
74
            /** @var AbstractEntity $result */
75
            $result = $this->factory->createFromData($row);
76
        }
77
78
        return $result;
79
    }
80
81
    /**
82
     * @param Condition $condition
83
     * @return AbstractEntity[]
84
     */
85
    public function findAll(Condition $condition): array
86
    {
87
        $result = [];
88
        $select = $this->selectQuery($condition);
89
        if ($rows = $select->execute()->fetchAll(\PDO::FETCH_ASSOC)) {
90
            foreach ($rows as $row) {
91
                $this->unserializeFields($row);
92
                /** @var AbstractEntity $entity */
93
                $entity = $this->factory->createFromData($row);
94
                $result[$entity->getId()] = $entity;
95
            }
96
        }
97
98
        return $result;
99
    }
100
101
    /**
102
     * @param Condition $condition
103
     * @return int
104
     */
105
    public function count(Condition $condition): int
106
    {
107
        $select = $this->selectQuery($condition);
108
        return $select->select(['id'])->execute()->rowCount();
109
    }
110
111
    /**
112
     * @param AbstractEntity $item
113
     */
114
    public function save(AbstractEntity $item)
115
    {
116
        $data = $this->hydrator->extract($item);
117
        $this->beforeDataSave($data);
118
        $this->serializeFields($data);
119
        if ($id = $item->getId()) {
120
            $this->db->update($this->table, $data, ['id' => $id]);
121
        } else {
122
            unset($data['id']);
123
            $this->db->insert($this->table, $data);
124
            $item->setId((int)$this->db->lastInsertId());
125
        }
126
    }
127
128
    /**
129
     * @param $id
130
     *
131
     * @throws \Doctrine\DBAL\Exception\InvalidArgumentException
132
     */
133
    public function delete($id)
134
    {
135
        $this->db->delete($this->table, ['id' => $id]);
136
    }
137
138
    /**
139
     * @param Condition|null $condition
140
     * @return QueryBuilder
141
     */
142
    protected function selectQuery(Condition $condition = null): QueryBuilder
143
    {
144
        $queryBuilder = $this->db->createQueryBuilder();
145
        $queryBuilder->select(['t1.*'])->from($this->table, 't1');
146
        $this->conditionParser->parse($queryBuilder, $condition);
147
        return $queryBuilder;
148
    }
149
150
    /**
151
     * Adjust data before save
152
     * @param $data
153
     */
154
    protected function beforeDataSave(&$data)
155
    {
156
    }
157
158
    /**
159
     * @param $data
160
     */
161
    private function serializeFields(&$data)
162
    {
163
        foreach ($this->serializeFields as $field) {
164
            if (isset($data[$field])) {
165
                $data[$field] = $this->serializeStrategy === self::SERIALIZE_STRATEGY_JSON
166
                    ? \json_encode($data[$field])
167
                    : \serialize($data[$field]);
168
            }
169
        }
170
    }
171
172
    /**
173
     * @param $row
174
     */
175
    private function unserializeFields(&$row)
176
    {
177
        foreach ($this->serializeFields as $field) {
178
            if (isset($row[$field])) {
179
                $row[$field] = $this->serializeStrategy === self::SERIALIZE_STRATEGY_JSON
180
                    ? \json_decode($row[$field], true)
181
                    : \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

181
                    : /** @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...
182
            }
183
        }
184
    }
185
}
186