ContentListSqlDataMapper::getByIdentifier()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 4
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 9
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace AbterPhp\Website\Orm\DataMappers;
6
7
use AbterPhp\Admin\Orm\DataMappers\IdGeneratorUserTrait;
8
use AbterPhp\Framework\Domain\Entities\IStringerEntity;
9
use AbterPhp\Website\Domain\Entities\ContentList as Entity;
10
use AbterPhp\Website\Domain\Entities\ContentListItem as Item;
11
use Opulence\Orm\DataMappers\SqlDataMapper;
12
use Opulence\QueryBuilders\Conditions\ConditionFactory;
13
use Opulence\QueryBuilders\Expression;
14
use Opulence\QueryBuilders\MySql\QueryBuilder;
15
use Opulence\QueryBuilders\MySql\SelectQuery;
16
use Opulence\QueryBuilders\Query;
17
use PDO;
18
19
/**
20
 * @phan-file-suppress PhanTypeMismatchArgument
21
 */
22
class ContentListSqlDataMapper extends SqlDataMapper implements IContentListDataMapper
23
{
24
    use IdGeneratorUserTrait;
25
26
    /**
27
     * @param IStringerEntity $entity
28
     */
29
    public function add($entity)
30
    {
31
        assert($entity instanceof Entity, new \InvalidArgumentException());
32
33
        $query = (new QueryBuilder())
34
            ->insert(
35
                'lists',
36
                [
37
                    'id'               => [$entity->getId(), PDO::PARAM_STR],
38
                    'name'             => [$entity->getName(), PDO::PARAM_STR],
39
                    'identifier'       => [$entity->getIdentifier(), PDO::PARAM_STR],
40
                    'classes'          => [$entity->getClasses(), PDO::PARAM_STR],
41
                    'protected'        => [$entity->isProtected(), PDO::PARAM_BOOL],
42
                    'with_links'       => [$entity->isWithLinks(), PDO::PARAM_BOOL],
43
                    'with_label_links' => [$entity->isWithLabelLinks(), PDO::PARAM_BOOL],
44
                    'with_html'        => [$entity->isWithHtml(), PDO::PARAM_BOOL],
45
                    'with_images'      => [$entity->isWithImages(), PDO::PARAM_BOOL],
46
                    'with_classes'     => [$entity->isWithClasses(), PDO::PARAM_BOOL],
47
                ]
48
            );
49
50
        $statement = $this->writeConnection->prepare($query->getSql());
51
        $statement->bindValues($query->getParameters());
52
        $statement->execute();
53
54
        $this->upsertItems($entity);
55
    }
56
57
    /**
58
     * @param IStringerEntity $entity
59
     *
60
     * @throws \Opulence\QueryBuilders\InvalidQueryException
61
     */
62
    public function delete($entity)
63
    {
64
        assert($entity instanceof Entity, new \InvalidArgumentException());
65
66
        $query = (new QueryBuilder())
67
            ->update('lists', 'lists', ['deleted_at' => new Expression('NOW()')])
68
            ->where('id = ?')
69
            ->addUnnamedPlaceholderValue($entity->getId(), PDO::PARAM_STR);
70
71
        $statement = $this->writeConnection->prepare($query->getSql());
72
        $statement->bindValues($query->getParameters());
73
        $statement->execute();
74
75
        $this->deleteItems($entity);
76
    }
77
78
    /**
79
     * @return Entity[]
80
     * @throws \Opulence\Orm\OrmException
81
     */
82
    public function getAll(): array
83
    {
84
        $query = $this->getBaseQuery();
85
86
        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...
87
    }
88
89
    /**
90
     * @param int      $limitFrom
91
     * @param int      $pageSize
92
     * @param string[] $orders
93
     * @param array    $conditions
94
     * @param array    $params
95
     *
96
     * @return Entity[]
97
     * @throws \Opulence\Orm\OrmException
98
     */
99
    public function getPage(int $limitFrom, int $pageSize, array $orders, array $conditions, array $params): array
100
    {
101
        $query = $this->getBaseQuery()
102
            ->limit($pageSize)
103
            ->offset($limitFrom);
104
105
        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...
106
            $query->orderBy('name ASC');
107
        }
108
        foreach ($orders as $order) {
109
            $query->addOrderBy($order);
110
        }
111
112
        foreach ($conditions as $condition) {
113
            $query->andWhere($condition);
114
        }
115
116
        $replaceCount = 1;
117
118
        $sql = $query->getSql();
119
        $sql = str_replace('SELECT', 'SELECT SQL_CALC_FOUND_ROWS', $sql, $replaceCount);
120
121
        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...
122
    }
123
124
    /**
125
     * @param int|string $id
126
     *
127
     * @return Entity|null
128
     * @throws \Opulence\Orm\OrmException
129
     */
130
    public function getById($id)
131
    {
132
        $query = $this->getBaseQuery()->andWhere('lists.id = :id');
133
134
        $parameters = [
135
            'id' => [$id, PDO::PARAM_STR],
136
        ];
137
138
        $sql = $query->getSql();
139
140
        return $this->read($sql, $parameters, 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\ContentList|null.
Loading history...
141
    }
142
143
    /**
144
     * @param string $identifier
145
     *
146
     * @return Entity|null
147
     * @throws \Opulence\Orm\OrmException
148
     */
149
    public function getByIdentifier(string $identifier): ?Entity
150
    {
151
        $query = $this->getBaseQuery()->andWhere('lists.identifier = :identifier');
152
153
        $parameters = [
154
            'identifier' => [$identifier, PDO::PARAM_STR],
155
        ];
156
157
        return $this->read($query->getSql(), $parameters, self::VALUE_TYPE_ENTITY, true);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->read($quer...ALUE_TYPE_ENTITY, true) could return the type array which is incompatible with the type-hinted return AbterPhp\Website\Domain\Entities\ContentList|null. Consider adding an additional type-check to rule them out.
Loading history...
158
    }
159
160
    /**
161
     * @param string[] $identifiers
162
     *
163
     * @return Entity[]
164
     * @throws \Opulence\Orm\OrmException
165
     */
166
    public function getByIdentifiers(array $identifiers): array
167
    {
168
        if (count($identifiers) === 0) {
169
            return [];
170
        }
171
172
        $conditions = new ConditionFactory();
173
        $query      = $this->getBaseQuery()->andWhere($conditions->in('lists.identifier', $identifiers));
174
175
        return $this->read($query->getSql(), $query->getParameters(), 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...
176
    }
177
178
    /**
179
     * @param IStringerEntity $entity
180
     *
181
     * @throws \Opulence\QueryBuilders\InvalidQueryException
182
     */
183
    public function update($entity)
184
    {
185
        assert($entity instanceof Entity, new \InvalidArgumentException());
186
187
        $query = (new QueryBuilder())
188
            ->update(
189
                'lists',
190
                'lists',
191
                [
192
                    'name'             => [$entity->getName(), PDO::PARAM_STR],
193
                    'identifier'       => [$entity->getIdentifier(), PDO::PARAM_STR],
194
                    'classes'          => [$entity->getClasses(), PDO::PARAM_STR],
195
                    'protected'        => [$entity->isProtected(), PDO::PARAM_BOOL],
196
                    'with_links'       => [$entity->isWithLinks(), PDO::PARAM_BOOL],
197
                    'with_label_links' => [$entity->isWithLabelLinks(), PDO::PARAM_BOOL],
198
                    'with_html'        => [$entity->isWithHtml(), PDO::PARAM_BOOL],
199
                    'with_images'      => [$entity->isWithImages(), PDO::PARAM_BOOL],
200
                    'with_classes'     => [$entity->isWithClasses(), PDO::PARAM_BOOL],
201
                ]
202
            )
203
            ->where('id = ?')
204
            ->andWhere('lists.deleted_at IS NULL')
205
            ->addUnnamedPlaceholderValue($entity->getId(), PDO::PARAM_STR);
206
207
        $statement = $this->writeConnection->prepare($query->getSql());
208
        $statement->bindValues($query->getParameters());
209
        $statement->execute();
210
211
        $this->upsertItems($entity);
212
    }
213
214
    /**
215
     * @param string[] $hash
216
     *
217
     * @return Entity
218
     */
219
    protected function loadEntity(array $hash)
220
    {
221
        return new Entity(
222
            $hash['id'],
223
            $hash['name'],
224
            $hash['identifier'],
225
            $hash['classes'],
226
            (bool)$hash['protected'],
227
            (bool)$hash['with_links'],
228
            (bool)$hash['with_label_links'],
229
            (bool)$hash['with_html'],
230
            (bool)$hash['with_images'],
231
            (bool)$hash['with_classes']
232
        );
233
    }
234
235
    /**
236
     * @return SelectQuery
237
     */
238
    private function getBaseQuery(): SelectQuery
239
    {
240
        /** @var SelectQuery $query */
241
        $query = (new QueryBuilder())
242
            ->select(
243
                'lists.id',
244
                'lists.name',
245
                'lists.identifier',
246
                'lists.classes',
247
                'lists.protected',
248
                'lists.with_links',
249
                'lists.with_label_links',
250
                'lists.with_html',
251
                'lists.with_images',
252
                'lists.with_classes'
253
            )
254
            ->from('lists')
255
            ->where('lists.deleted_at IS NULL');
256
257
        return $query;
258
    }
259
260
    /**
261
     * @param Entity $entity
262
     */
263
    protected function upsertItems(Entity $entity)
264
    {
265
        if (!$entity->getItems()) {
266
            return;
267
        }
268
269
        foreach ($entity->getItems() as $item) {
270
            if (!$item->getId() && $item->isDeleted()) {
271
                continue;
272
            }
273
274
            $query = $item->getId() ? $this->createUpdateQuery($item) : $this->createInsertQuery($item);
275
276
            $sql = $query->getSql();
277
278
            $statement = $this->writeConnection->prepare($sql);
279
            $statement->bindValues($query->getParameters());
280
            $statement->execute();
281
        }
282
    }
283
284
    /**
285
     * @param Item $item
286
     *
287
     * @return Query
288
     */
289
    protected function createUpdateQuery(Item $item): Query
290
    {
291
        $deletedAt = $item->isDeleted()
292
            ? new Expression('NOW()')
293
            : [null, \PDO::PARAM_STR];
294
295
        return (new QueryBuilder())
296
            ->update(
297
                'list_items',
298
                'list_items',
299
                [
300
                    'list_id'      => [$item->getListId(), \PDO::PARAM_STR],
301
                    'label'        => [$item->getLabel(), \PDO::PARAM_STR],
302
                    'label_href'   => [$item->getLabelHref(), \PDO::PARAM_STR],
303
                    'content'      => [$item->getContent(), \PDO::PARAM_STR],
304
                    'content_href' => [$item->getContentHref(), \PDO::PARAM_STR],
305
                    'img_src'      => [$item->getImgSrc(), \PDO::PARAM_STR],
306
                    'img_alt'      => [$item->getImgAlt(), \PDO::PARAM_STR],
307
                    'img_href'     => [$item->getImgHref(), \PDO::PARAM_STR],
308
                    'classes'      => [$item->getClasses(), \PDO::PARAM_STR],
309
                    'deleted_at'   => $deletedAt,
310
                ]
311
            )
312
            ->where('id = ?')
313
            ->addUnnamedPlaceholderValue($item->getId(), \PDO::PARAM_STR);
314
    }
315
316
    /**
317
     * @param Item $item
318
     *
319
     * @return Query
320
     */
321
    protected function createInsertQuery(Item $item): Query
322
    {
323
        return (new QueryBuilder())
324
            ->insert(
325
                'list_items',
326
                [
327
                    'id'           => [$this->getIdGenerator()->generate($item), \PDO::PARAM_STR],
328
                    'list_id'      => [$item->getListId(), \PDO::PARAM_STR],
329
                    'label'        => [$item->getLabel(), \PDO::PARAM_STR],
330
                    'label_href'   => [$item->getLabelHref(), \PDO::PARAM_STR],
331
                    'content'      => [$item->getContent(), \PDO::PARAM_STR],
332
                    'content_href' => [$item->getContentHref(), \PDO::PARAM_STR],
333
                    'img_src'      => [$item->getImgSrc(), \PDO::PARAM_STR],
334
                    'img_alt'      => [$item->getImgAlt(), \PDO::PARAM_STR],
335
                    'img_href'     => [$item->getImgHref(), \PDO::PARAM_STR],
336
                    'classes'      => [$item->getClasses(), \PDO::PARAM_STR],
337
                ]
338
            );
339
    }
340
341
    /**
342
     * @param Entity $entity
343
     */
344
    protected function deleteItems(Entity $entity)
345
    {
346
        $query = (new QueryBuilder())
347
            ->update('list_items', 'list_items', ['deleted_at' => new Expression('NOW()')])
348
            ->where('list_id = ?')
349
            ->andWhere('deleted_at IS NOT NULL')
350
            ->addUnnamedPlaceholderValue($entity->getId(), \PDO::PARAM_STR);
351
352
        $sql = $query->getSql();
353
354
        $statement = $this->writeConnection->prepare($sql);
355
        $statement->bindValues($query->getParameters());
356
        $statement->execute();
357
    }
358
}
359