Issues (106)

src/Orm/DataMappers/BlockSqlDataMapper.php (6 issues)

1
<?php
2
3
declare(strict_types=1);
4
5
namespace AbterPhp\Website\Orm\DataMappers;
6
7
use AbterPhp\Framework\Domain\Entities\IStringerEntity;
8
use AbterPhp\Website\Domain\Entities\Block as Entity;
9
use Opulence\Orm\DataMappers\SqlDataMapper;
10
use Opulence\QueryBuilders\Conditions\ConditionFactory;
11
use Opulence\QueryBuilders\Expression;
12
use Opulence\QueryBuilders\MySql\QueryBuilder;
13
use Opulence\QueryBuilders\MySql\SelectQuery;
14
use PDO;
15
16
/** @phan-file-suppress PhanTypeMismatchArgument */
17
18
class BlockSqlDataMapper extends SqlDataMapper implements IBlockDataMapper
19
{
20
    /**
21
     * @param IStringerEntity $entity
22
     */
23
    public function add($entity)
24
    {
25
        assert($entity instanceof Entity, new \InvalidArgumentException());
26
27
        $layoutIdType = PDO::PARAM_NULL;
28
        if ($entity->getLayoutId()) {
29
            $layoutIdType = PDO::PARAM_STR;
30
        }
31
        $query = (new QueryBuilder())
32
            ->insert(
33
                'blocks',
34
                [
35
                    'id'         => [$entity->getId(), PDO::PARAM_STR],
36
                    'identifier' => [$entity->getIdentifier(), PDO::PARAM_STR],
37
                    'title'      => [$entity->getTitle(), PDO::PARAM_STR],
38
                    'body'       => [$entity->getBody(), PDO::PARAM_STR],
39
                    'layout'     => [$entity->getLayout(), PDO::PARAM_STR],
40
                    'layout_id'  => [$entity->getLayoutId(), $layoutIdType],
41
                ]
42
            );
43
44
        $statement = $this->writeConnection->prepare($query->getSql());
45
        $statement->bindValues($query->getParameters());
46
        $statement->execute();
47
    }
48
49
    /**
50
     * @param IStringerEntity $entity
51
     *
52
     * @throws \Opulence\QueryBuilders\InvalidQueryException
53
     */
54
    public function delete($entity)
55
    {
56
        assert($entity instanceof Entity, new \InvalidArgumentException());
57
58
        $query = (new QueryBuilder())
59
            ->update('blocks', 'blocks', ['deleted_at' => new Expression('NOW()')])
60
            ->where('id = ?')
61
            ->addUnnamedPlaceholderValue($entity->getId(), PDO::PARAM_STR);
62
63
        $statement = $this->writeConnection->prepare($query->getSql());
64
        $statement->bindValues($query->getParameters());
65
        $statement->execute();
66
    }
67
68
    /**
69
     * @return Entity[]
70
     * @throws \Opulence\Orm\OrmException
71
     */
72
    public function getAll(): array
73
    {
74
        $query = $this->getBaseQuery();
75
76
        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...
77
    }
78
79
    /**
80
     * @param int      $limitFrom
81
     * @param int      $pageSize
82
     * @param string[] $orders
83
     * @param array    $conditions
84
     * @param array    $params
85
     *
86
     * @return Entity[]
87
     * @throws \Opulence\Orm\OrmException
88
     */
89
    public function getPage(int $limitFrom, int $pageSize, array $orders, array $conditions, array $params): array
90
    {
91
        $query = $this->getBaseQuery()
92
            ->limit($pageSize)
93
            ->offset($limitFrom);
94
95
        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...
96
            $query->orderBy('title ASC');
97
        }
98
        foreach ($orders as $order) {
99
            $query->addOrderBy($order);
100
        }
101
102
        foreach ($conditions as $condition) {
103
            $query->andWhere($condition);
104
        }
105
106
        $replaceCount = 1;
107
108
        $sql = $query->getSql();
109
        $sql = str_replace('SELECT', 'SELECT SQL_CALC_FOUND_ROWS', $sql, $replaceCount);
110
111
        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...
112
    }
113
114
    /**
115
     * @param int|string $id
116
     *
117
     * @return Entity|null
118
     * @throws \Opulence\Orm\OrmException
119
     */
120
    public function getById($id)
121
    {
122
        $query = $this->getBaseQuery()->andWhere('blocks.id = :block_id');
123
124
        $parameters = [
125
            'block_id' => [$id, PDO::PARAM_STR],
126
        ];
127
128
        $sql = $query->getSql();
129
130
        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\Block|null.
Loading history...
131
    }
132
133
    /**
134
     * @param string $identifier
135
     *
136
     * @return Entity|null
137
     * @throws \Opulence\Orm\OrmException
138
     */
139
    public function getByIdentifier(string $identifier): ?Entity
140
    {
141
        $query = $this->getBaseQuery()->andWhere('blocks.identifier = :identifier');
142
143
        $parameters = [
144
            'identifier' => [$identifier, PDO::PARAM_STR],
145
        ];
146
147
        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\Block|null. Consider adding an additional type-check to rule them out.
Loading history...
148
    }
149
150
    /**
151
     * @param string[] $identifiers
152
     *
153
     * @return Entity[]
154
     * @throws \Opulence\Orm\OrmException
155
     */
156
    public function getWithLayoutByIdentifiers(array $identifiers): array
157
    {
158
        if (count($identifiers) === 0) {
159
            return [];
160
        }
161
162
        $conditions = new ConditionFactory();
163
        $query      = $this->getWithLayoutQuery()->andWhere($conditions->in('blocks.identifier', $identifiers));
164
165
        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...
166
    }
167
168
    /**
169
     * @param IStringerEntity $entity
170
     *
171
     * @throws \Opulence\QueryBuilders\InvalidQueryException
172
     */
173
    public function update($entity)
174
    {
175
        assert($entity instanceof Entity, new \InvalidArgumentException());
176
177
        $layoutIdType = $entity->getLayoutId() ? PDO::PARAM_STR : PDO::PARAM_NULL;
178
179
        $query = (new QueryBuilder())
180
            ->update(
181
                'blocks',
182
                'blocks',
183
                [
184
                    'identifier' => [$entity->getIdentifier(), PDO::PARAM_STR],
185
                    'title'      => [$entity->getTitle(), PDO::PARAM_STR],
186
                    'body'       => [$entity->getBody(), PDO::PARAM_STR],
187
                    'layout'     => [$entity->getLayout(), PDO::PARAM_STR],
188
                    'layout_id'  => [$entity->getLayoutId(), $layoutIdType],
189
                ]
190
            )
191
            ->where('id = ?')
192
            ->andWhere('deleted_at IS NULL')
193
            ->addUnnamedPlaceholderValue($entity->getId(), PDO::PARAM_STR);
194
195
        $statement = $this->writeConnection->prepare($query->getSql());
196
        $statement->bindValues($query->getParameters());
197
        $statement->execute();
198
    }
199
200
    /**
201
     * @param array $hash
202
     *
203
     * @return Entity
204
     */
205
    protected function loadEntity(array $hash)
206
    {
207
        $layoutId = $hash['layout_id'] ?: null;
208
209
        return new Entity(
210
            $hash['id'],
211
            $hash['identifier'],
212
            $hash['title'],
213
            $hash['body'],
214
            $hash['layout'],
215
            $layoutId
216
        );
217
    }
218
219
    /**
220
     * @return SelectQuery
221
     */
222
    private function getBaseQuery(): SelectQuery
223
    {
224
        /** @var SelectQuery $query */
225
        $query = (new QueryBuilder())
226
            ->select(
227
                'blocks.id',
228
                'blocks.identifier',
229
                'blocks.title',
230
                'blocks.body',
231
                'blocks.layout_id',
232
                'blocks.layout'
233
            )
234
            ->from('blocks')
235
            ->where('blocks.deleted_at IS NULL');
236
237
        return $query;
238
    }
239
240
    /**
241
     * @return SelectQuery
242
     */
243
    private function getWithLayoutQuery(): SelectQuery
244
    {
245
        /** @var SelectQuery $query */
246
        $query = (new QueryBuilder())
247
            ->select(
248
                'blocks.id',
249
                'blocks.identifier',
250
                'blocks.title',
251
                'blocks.body',
252
                'blocks.layout_id',
253
                'COALESCE(layouts.body, blocks.layout) AS layout'
254
            )
255
            ->from('blocks')
256
            ->leftJoin('block_layouts', 'layouts', 'layouts.id = blocks.layout_id AND layouts.deleted_at IS NULL')
257
            ->where('blocks.deleted_at IS NULL');
258
259
        return $query;
260
    }
261
}
262