PageCategorySqlDataMapper::getPage()   A
last analyzed

Complexity

Conditions 4
Paths 8

Size

Total Lines 23
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 13
c 1
b 0
f 0
nc 8
nop 5
dl 0
loc 23
rs 9.8333
1
<?php
2
3
declare(strict_types=1);
4
5
namespace AbterPhp\Website\Orm\DataMappers;
6
7
use AbterPhp\Admin\Domain\Entities\UserGroup;
8
use AbterPhp\Admin\Orm\DataMappers\IdGeneratorUserTrait;
9
use AbterPhp\Framework\Domain\Entities\IStringerEntity;
10
use AbterPhp\Website\Domain\Entities\PageCategory as Entity;
11
use Opulence\Orm\DataMappers\SqlDataMapper;
12
use Opulence\QueryBuilders\Expression;
13
use Opulence\QueryBuilders\MySql\QueryBuilder;
14
use Opulence\QueryBuilders\MySql\SelectQuery;
15
16
/**
17
 * @phan-file-suppress PhanTypeMismatchArgument
18
 */
19
class PageCategorySqlDataMapper extends SqlDataMapper implements IPageCategoryDataMapper
20
{
21
    use IdGeneratorUserTrait;
22
23
    const USER_GROUP_IDS = 'user_group_ids';
24
25
    /**
26
     * @param IStringerEntity $entity
27
     */
28
    public function add($entity)
29
    {
30
        assert($entity instanceof Entity, new \InvalidArgumentException());
31
32
        $data  = $this->getColumnNamesToValues($entity, true);
33
        $query = (new QueryBuilder())->insert('page_categories', $data);
34
35
        $sql    = $query->getSql();
36
        $params = $query->getParameters();
37
38
        $statement = $this->writeConnection->prepare($sql);
39
        $statement->bindValues($params);
40
        $statement->execute();
41
42
        $this->addUserGroups($entity);
43
    }
44
45
    /**
46
     * @param IStringerEntity $entity
47
     */
48
    public function delete($entity)
49
    {
50
        assert($entity instanceof Entity, new \InvalidArgumentException());
51
52
        $query = (new QueryBuilder())
53
            ->update('page_categories', 'page_categories', ['deleted_at' => new Expression('NOW()')])
54
            ->where('id = ?')
55
            ->addUnnamedPlaceholderValue($entity->getId(), \PDO::PARAM_STR);
56
57
        $sql    = $query->getSql();
58
        $params = $query->getParameters();
59
60
        $statement = $this->writeConnection->prepare($sql);
61
        $statement->bindValues($params);
62
        $statement->execute();
63
64
        $this->deleteUserGroups($entity);
65
    }
66
67
    /**
68
     * @return Entity[]
69
     */
70
    public function getAll(): array
71
    {
72
        $query = $this->getBaseQuery();
73
74
        return $this->read($query->getSql(), [], self::VALUE_TYPE_ARRAY);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->read($quer...self::VALUE_TYPE_ARRAY) could return the type null which is incompatible with the type-hinted return array. Consider adding an additional type-check to rule them out.
Loading history...
75
    }
76
77
    /**
78
     * @param int      $limitFrom
79
     * @param int      $pageSize
80
     * @param string[] $orders
81
     * @param array    $conditions
82
     * @param array    $params
83
     *
84
     * @return Entity[]
85
     */
86
    public function getPage(int $limitFrom, int $pageSize, array $orders, array $conditions, array $params): array
87
    {
88
        $query = $this->getBaseQuery()
89
            ->limit($pageSize)
90
            ->offset($limitFrom);
91
92
        if (!$orders) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $orders of type string[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
93
            $query->orderBy('pc.name ASC');
94
        }
95
        foreach ($orders as $order) {
96
            $query->addOrderBy($order);
97
        }
98
99
        foreach ($conditions as $condition) {
100
            $query->andWhere($condition);
101
        }
102
103
        $replaceCount = 1;
104
105
        $sql = $query->getSql();
106
        $sql = str_replace('SELECT', 'SELECT SQL_CALC_FOUND_ROWS', $sql, $replaceCount);
107
108
        return $this->read($sql, $params, self::VALUE_TYPE_ARRAY);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->read($sql,...self::VALUE_TYPE_ARRAY) could return the type null which is incompatible with the type-hinted return array. Consider adding an additional type-check to rule them out.
Loading history...
109
    }
110
111
    /**
112
     * @param int|string $id
113
     *
114
     * @return Entity|null
115
     */
116
    public function getById($id)
117
    {
118
        $query = $this->getBaseQuery()->andWhere('pc.id = :category_id');
119
120
        $sql    = $query->getSql();
121
        $params = [
122
            'category_id' => [$id, \PDO::PARAM_STR],
123
        ];
124
125
126
        return $this->read($sql, $params, self::VALUE_TYPE_ENTITY, true);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->read($sql,...ALUE_TYPE_ENTITY, true) also could return the type array which is incompatible with the documented return type AbterPhp\Website\Domain\Entities\PageCategory|null.
Loading history...
127
    }
128
129
    /**
130
     * @param string $identifier
131
     *
132
     * @return Entity|null
133
     * @throws \Opulence\Orm\OrmException
134
     */
135
    public function getByIdentifier(string $identifier): ?Entity
136
    {
137
        $query = $this->getBaseQuery()->andWhere('identifier = :identifier');
138
139
        $sql    = $query->getSql();
140
        $params = [
141
            'identifier' => $identifier,
142
        ];
143
144
        return $this->read($sql, $params, self::VALUE_TYPE_ENTITY, true);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->read($sql,...ALUE_TYPE_ENTITY, true) could return the type array which is incompatible with the type-hinted return AbterPhp\Website\Domain\Entities\PageCategory|null. Consider adding an additional type-check to rule them out.
Loading history...
145
    }
146
147
    /**
148
     * @param IStringerEntity $entity
149
     */
150
    public function update($entity)
151
    {
152
        assert($entity instanceof Entity, new \InvalidArgumentException());
153
154
        $columnNamesToValues = $this->getColumnNamesToValues($entity, false);
155
156
        $query = (new QueryBuilder())
157
            ->update('page_categories', 'page_categories', $columnNamesToValues)
158
            ->where('id = ?')
159
            ->andWhere('deleted_at IS NULL')
160
            ->addUnnamedPlaceholderValue($entity->getId(), \PDO::PARAM_STR);
161
162
        $sql    = $query->getSql();
163
        $params = $query->getParameters();
164
165
        $statement = $this->writeConnection->prepare($sql);
166
        $statement->bindValues($params);
167
        $statement->execute();
168
169
        $this->deleteUserGroups($entity);
170
        $this->addUserGroups($entity);
171
    }
172
173
    /**
174
     * @param Entity $entity
175
     * @param bool   $create
176
     *
177
     * @return array
178
     */
179
    protected function getColumnNamesToValues(Entity $entity, bool $create): array
180
    {
181
        $columnNamesToValues = [
182
            'name'       => [$entity->getName(), \PDO::PARAM_STR],
183
            'identifier' => [$entity->getIdentifier(), \PDO::PARAM_STR],
184
        ];
185
186
        if ($create) {
187
            $columnNamesToValues = array_merge(['id' => [$entity->getId(), \PDO::PARAM_STR]], $columnNamesToValues);
188
        }
189
190
        return $columnNamesToValues;
191
    }
192
193
    /**
194
     * @param Entity $entity
195
     */
196
    protected function deleteUserGroups(Entity $entity)
197
    {
198
        $query = (new QueryBuilder())
199
            ->delete('user_groups_page_categories')
200
            ->where('page_category_id = ?')
201
            ->addUnnamedPlaceholderValue($entity->getId(), \PDO::PARAM_STR);
202
203
        $sql = $query->getSql();
204
205
        $statement = $this->writeConnection->prepare($sql);
206
        $statement->bindValues($query->getParameters());
207
        $statement->execute();
208
    }
209
210
    /**
211
     * @param Entity $entity
212
     */
213
    protected function addUserGroups(Entity $entity)
214
    {
215
        $idGenerator = $this->getIdGenerator();
216
217
        foreach ($entity->getUserGroups() as $userGroup) {
218
            $query = (new QueryBuilder())
219
                ->insert(
220
                    'user_groups_page_categories',
221
                    [
222
                        'id'               => [$idGenerator->generate($userGroup), \PDO::PARAM_STR],
223
                        'user_group_id'    => [$userGroup->getId(), \PDO::PARAM_STR],
224
                        'page_category_id' => [$entity->getId(), \PDO::PARAM_STR],
225
                    ]
226
                );
227
228
            $sql = $query->getSql();
229
230
            $statement = $this->writeConnection->prepare($sql);
231
            $statement->bindValues($query->getParameters());
232
            $statement->execute();
233
        }
234
    }
235
236
    /**
237
     * @param array $hash
238
     *
239
     * @return Entity
240
     */
241
    protected function loadEntity(array $hash)
242
    {
243
        $userGroups = $this->loadUserGroups($hash);
244
245
        return new Entity(
246
            $hash['id'],
247
            $hash['name'],
248
            $hash['identifier'],
249
            $userGroups
250
        );
251
    }
252
253
    /**
254
     * @param array $hash
255
     *
256
     * @return array
257
     */
258
    private function loadUserGroups(array $hash): array
259
    {
260
        if (empty($hash[static::USER_GROUP_IDS])) {
261
            return [];
262
        }
263
264
        $userGroups = [];
265
        foreach (explode(',', $hash[static::USER_GROUP_IDS]) as $id) {
266
            $userGroups[] = new UserGroup((string)$id, '', '');
267
        }
268
269
        return $userGroups;
270
    }
271
272
    /**
273
     * @return SelectQuery
274
     */
275
    private function getBaseQuery()
276
    {
277
        /** @var SelectQuery $query */
278
        $query = (new QueryBuilder())
279
            ->select(
280
                'pc.id',
281
                'pc.name',
282
                'pc.identifier',
283
                'GROUP_CONCAT(ugpc.user_group_id) AS user_group_ids'
284
            )
285
            ->from('page_categories', 'pc')
286
            ->leftJoin('user_groups_page_categories', 'ugpc', 'ugpc.page_category_id = pc.id')
287
            ->where('pc.deleted_at IS NULL')
288
            ->groupBy('pc.id');
289
290
        return $query;
291
    }
292
}
293