Passed
Pull Request — master (#1)
by Peter
03:06
created

ContentListSqlDataMapper::update()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 27
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 19
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 27
rs 9.6333
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\Framework\Helper\DateHelper;
10
use AbterPhp\Website\Domain\Entities\ContentList as Entity;
11
use AbterPhp\Website\Domain\Entities\ContentListItem;
12
use Opulence\Orm\DataMappers\SqlDataMapper;
13
use Opulence\QueryBuilders\MySql\QueryBuilder;
14
use Opulence\QueryBuilders\MySql\SelectQuery;
15
use Opulence\QueryBuilders\Query;
16
use PDO;
17
18
/**
19
 * @phan-file-suppress PhanTypeMismatchArgument
20
 */
21
class ContentListSqlDataMapper extends SqlDataMapper implements IContentListDataMapper
22
{
23
    use IdGeneratorUserTrait;
24
25
    /**
26
     * @param IStringerEntity $entity
27
     */
28
    public function add($entity)
29
    {
30
        assert($entity instanceof Entity, new \InvalidArgumentException());
31
32
        $query = (new QueryBuilder())
33
            ->insert(
34
                'lists',
35
                [
36
                    'id'         => [$entity->getId(), PDO::PARAM_STR],
37
                    'type_id'    => [$entity->getTypeId(), PDO::PARAM_STR],
38
                    'name'       => [$entity->getName(), PDO::PARAM_STR],
39
                    'identifier' => [$entity->getIdentifier(), PDO::PARAM_STR],
40
                    'protected'  => [$entity->isProtected(), PDO::PARAM_BOOL],
41
                    'with_image' => [$entity->isWithImage(), PDO::PARAM_BOOL],
42
                    'with_links' => [$entity->isWithLinks(), PDO::PARAM_BOOL],
43
                    'with_html'  => [$entity->isWithHtml(), PDO::PARAM_BOOL],
44
                ]
45
            );
46
47
        $statement = $this->writeConnection->prepare($query->getSql());
48
        $statement->bindValues($query->getParameters());
49
        $statement->execute();
50
51
        $this->upsertItems($entity);
52
    }
53
54
    /**
55
     * @param IStringerEntity $entity
56
     *
57
     * @throws \Opulence\QueryBuilders\InvalidQueryException
58
     */
59
    public function delete($entity)
60
    {
61
        assert($entity instanceof Entity, new \InvalidArgumentException());
62
63
        $query = (new QueryBuilder())
64
            ->update('lists', 'lists', ['deleted_at' => [(new \DateTime())->format(\DATE_RFC3339), \PDO::PARAM_STR]])
65
            ->where('id = ?')
66
            ->addUnnamedPlaceholderValue($entity->getId(), PDO::PARAM_STR);
67
68
        $statement = $this->writeConnection->prepare($query->getSql());
69
        $statement->bindValues($query->getParameters());
70
        $statement->execute();
71
72
        $this->deleteItems($entity);
73
    }
74
75
    /**
76
     * @return Entity[]
77
     * @throws \Opulence\Orm\OrmException
78
     */
79
    public function getAll(): array
80
    {
81
        $query = $this->getBaseQuery();
82
83
        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...
84
    }
85
86
    /**
87
     * @param int      $limitFrom
88
     * @param int      $pageSize
89
     * @param string[] $orders
90
     * @param array    $conditions
91
     * @param array    $params
92
     *
93
     * @return Entity[]
94
     * @throws \Opulence\Orm\OrmException
95
     */
96
    public function getPage(int $limitFrom, int $pageSize, array $orders, array $conditions, array $params): array
97
    {
98
        $query = $this->getBaseQuery()
99
            ->limit($pageSize)
100
            ->offset($limitFrom);
101
102
        foreach ($orders as $order) {
103
            $query->addOrderBy($order);
104
        }
105
106
        foreach ($conditions as $condition) {
107
            $query->andWhere($condition);
108
        }
109
110
        $replaceCount = 1;
111
112
        $sql = $query->getSql();
113
        $sql = str_replace('SELECT', 'SELECT SQL_CALC_FOUND_ROWS', $sql, $replaceCount);
114
115
        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...
116
    }
117
118
    /**
119
     * @param int|string $id
120
     *
121
     * @return Entity|null
122
     * @throws \Opulence\Orm\OrmException
123
     */
124
    public function getById($id)
125
    {
126
        $query = $this->getBaseQuery()->andWhere('lists.id = :list_id');
127
128
        $parameters = [
129
            'list_id' => [$id, PDO::PARAM_STR],
130
        ];
131
132
        $sql = $query->getSql();
133
134
        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...
135
    }
136
137
    /**
138
     * @param string $identifier
139
     *
140
     * @return Entity|null
141
     * @throws \Opulence\Orm\OrmException
142
     */
143
    public function getByIdentifier(string $identifier): ?Entity
144
    {
145
        $query = $this->getBaseQuery()->andWhere('lists.identifier = :identifier');
146
147
        $parameters = [
148
            'identifier' => [$identifier, PDO::PARAM_STR],
149
        ];
150
151
        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...
152
    }
153
154
    /**
155
     * @param IStringerEntity $entity
156
     *
157
     * @throws \Opulence\QueryBuilders\InvalidQueryException
158
     */
159
    public function update($entity)
160
    {
161
        assert($entity instanceof Entity, new \InvalidArgumentException());
162
163
        $query = (new QueryBuilder())
164
            ->update(
165
                'lists',
166
                'lists',
167
                [
168
                    'type_id'    => [$entity->getTypeId(), PDO::PARAM_STR],
169
                    'name'       => [$entity->getName(), PDO::PARAM_STR],
170
                    'identifier' => [$entity->getIdentifier(), PDO::PARAM_STR],
171
                    'protected'  => [$entity->isProtected(), PDO::PARAM_BOOL],
172
                    'with_image' => [$entity->isWithImage(), PDO::PARAM_BOOL],
173
                    'with_links' => [$entity->isWithLinks(), PDO::PARAM_BOOL],
174
                    'with_html'  => [$entity->isWithHtml(), PDO::PARAM_BOOL],
175
                ]
176
            )
177
            ->where('id = ?')
178
            ->andWhere('lists.deleted_at IS NULL')
179
            ->addUnnamedPlaceholderValue($entity->getId(), PDO::PARAM_STR);
180
181
        $statement = $this->writeConnection->prepare($query->getSql());
182
        $statement->bindValues($query->getParameters());
183
        $statement->execute();
184
185
        $this->upsertItems($entity);
186
    }
187
188
    /**
189
     * @param array $hash
190
     *
191
     * @return Entity
192
     */
193
    protected function loadEntity(array $hash)
194
    {
195
        return new Entity(
196
            $hash['id'],
197
            $hash['type_id'],
198
            $hash['name'],
199
            $hash['identifier'],
200
            (bool)$hash['protected'],
201
            (bool)$hash['with_image'],
202
            (bool)$hash['with_links'],
203
            (bool)$hash['with_html']
204
        );
205
    }
206
207
    /**
208
     * @return SelectQuery
209
     */
210
    private function getBaseQuery(): SelectQuery
211
    {
212
        /** @var SelectQuery $query */
213
        $query = (new QueryBuilder())
214
            ->select(
215
                'lists.id',
216
                'lists.type_id',
217
                'lists.name',
218
                'lists.identifier',
219
                'lists.protected',
220
                'lists.with_image',
221
                'lists.with_links',
222
                'lists.with_html'
223
            )
224
            ->from('lists')
225
            ->where('lists.deleted_at IS NULL');
226
227
        return $query;
228
    }
229
230
    /**
231
     * @param Entity $entity
232
     */
233
    protected function upsertItems(Entity $entity)
234
    {
235
        foreach ($entity->getItems() as $item) {
236
            if (!$item->getId() && $item->getDeletedAt()) {
237
                continue;
238
            }
239
240
            $query = $item->getId() ? $this->createUpdateQuery($item) : $this->createInsertQuery($item);
241
242
            $sql = $query->getSql();
243
244
            $statement = $this->writeConnection->prepare($sql);
245
            $statement->bindValues($query->getParameters());
246
            $statement->execute();
247
        }
248
    }
249
250
    /**
251
     * @param ContentListItem $item
252
     *
253
     * @return Query
254
     */
255
    protected function createUpdateQuery(ContentListItem $item): Query
256
    {
257
        $deletedAt = $item->getDeletedAt()
258
            ? [DateHelper::mysqlDateTime($item->getDeletedAt()), \PDO::PARAM_STR]
259
            : [null, \PDO::PARAM_STR];
260
261
        return (new QueryBuilder())
262
            ->update(
263
                'list_items',
264
                'list_items',
265
                [
266
                    'list_id'    => [$item->getListId(), \PDO::PARAM_STR],
267
                    'name'       => [$item->getName(), \PDO::PARAM_STR],
268
                    'name_href'  => [$item->getNameHref(), \PDO::PARAM_STR],
269
                    'body'       => [$item->getBody(), \PDO::PARAM_STR],
270
                    'body_href'  => [$item->getBodyHref(), \PDO::PARAM_STR],
271
                    'img_src'    => [$item->getImgSrc(), \PDO::PARAM_STR],
272
                    'img_alt'    => [$item->getImgAlt(), \PDO::PARAM_STR],
273
                    'img_href'   => [$item->getImgHref(), \PDO::PARAM_STR],
274
                    'deleted_at' => $deletedAt,
275
                ]
276
            )
277
            ->where('id = ?')
278
            ->addUnnamedPlaceholderValue($item->getId(), \PDO::PARAM_STR);
279
    }
280
281
    /**
282
     * @param ContentListItem $item
283
     *
284
     * @return Query
285
     */
286
    protected function createInsertQuery(ContentListItem $item): Query
287
    {
288
        return (new QueryBuilder())
289
            ->insert(
290
                'list_items',
291
                [
292
                    'id'        => [$this->getIdGenerator()->generate($item), \PDO::PARAM_STR],
293
                    'list_id'   => [$item->getListId(), \PDO::PARAM_STR],
294
                    'name'      => [$item->getName(), \PDO::PARAM_STR],
295
                    'name_href' => [$item->getNameHref(), \PDO::PARAM_STR],
296
                    'body'      => [$item->getBody(), \PDO::PARAM_STR],
297
                    'body_href' => [$item->getBodyHref(), \PDO::PARAM_STR],
298
                    'img_src'   => [$item->getImgSrc(), \PDO::PARAM_STR],
299
                    'img_alt'   => [$item->getImgAlt(), \PDO::PARAM_STR],
300
                    'img_href'  => [$item->getImgHref(), \PDO::PARAM_STR],
301
                ]
302
            );
303
    }
304
305
    /**
306
     * @param Entity $entity
307
     */
308
    protected function deleteItems(Entity $entity)
309
    {
310
        $query = (new QueryBuilder())
311
            ->update('list_items', 'list_items', ['deleted_at' => [DateHelper::mysqlDateTime(), \PDO::PARAM_STR]])
312
            ->where('list_id = ?')
313
            ->andWhere('deleted_at IS NOT NULL')
314
            ->addUnnamedPlaceholderValue($entity->getId(), \PDO::PARAM_STR);
315
316
        $sql = $query->getSql();
317
318
        $statement = $this->writeConnection->prepare($sql);
319
        $statement->bindValues($query->getParameters());
320
        $statement->execute();
321
    }
322
}
323