Issues (104)

src/Orm/DataMappers/ApiClientSqlDataMapper.php (4 issues)

1
<?php
2
3
declare(strict_types=1);
4
5
namespace AbterPhp\Admin\Orm\DataMappers;
6
7
use AbterPhp\Admin\Domain\Entities\AdminResource;
8
use AbterPhp\Admin\Domain\Entities\ApiClient as Entity;
9
use AbterPhp\Framework\Domain\Entities\IStringerEntity;
10
use Opulence\Orm\DataMappers\SqlDataMapper;
11
use Opulence\Orm\OrmException;
12
use Opulence\QueryBuilders\Expression;
13
use Opulence\QueryBuilders\InvalidQueryException;
14
use Opulence\QueryBuilders\MySql\QueryBuilder;
15
use Opulence\QueryBuilders\SelectQuery;
16
17
/** @phan-file-suppress PhanTypeMismatchArgument */
18
19
class ApiClientSqlDataMapper extends SqlDataMapper implements IApiClientDataMapper
20
{
21
    use IdGeneratorUserTrait;
22
23
    /**
24
     * @param IStringerEntity $entity
25
     */
26
    public function add($entity)
27
    {
28
        assert($entity instanceof Entity, new \InvalidArgumentException());
29
30
        $query = (new QueryBuilder())
31
            ->insert(
32
                'api_clients',
33
                [
34
                    'id'          => [$entity->getId(), \PDO::PARAM_STR],
35
                    'user_id'     => [$entity->getUserId(), \PDO::PARAM_STR],
36
                    'description' => [$entity->getDescription(), \PDO::PARAM_STR],
37
                    'secret'      => [$entity->getSecret(), \PDO::PARAM_STR],
38
                ]
39
            );
40
41
        $sql    = $query->getSql();
42
        $params = $query->getParameters();
43
44
        $statement = $this->writeConnection->prepare($sql);
45
        $statement->bindValues($params);
46
        $statement->execute();
47
48
        $this->addAdminResources($entity);
49
    }
50
51
    /**
52
     * @param IStringerEntity $entity
53
     *
54
     * @throws InvalidQueryException
55
     */
56
    public function delete($entity)
57
    {
58
        assert($entity instanceof Entity, new \InvalidArgumentException());
59
60
        $this->deleteAdminResources($entity);
61
62
        $query = (new QueryBuilder())
63
            ->update('api_clients', 'api_clients', ['deleted_at' => new Expression('NOW()')])
64
            ->where('id = ?')
65
            ->addUnnamedPlaceholderValue($entity->getId(), \PDO::PARAM_STR);
66
67
        $statement = $this->writeConnection->prepare($query->getSql());
68
        $statement->bindValues($query->getParameters());
69
        $statement->execute();
70
    }
71
72
    /**
73
     * @return Entity[]
74
     * @throws OrmException
75
     */
76
    public function getAll(): array
77
    {
78
        $query = $this->getBaseQuery();
79
80
        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...
81
    }
82
83
    /**
84
     * @param int      $limitFrom
85
     * @param int      $pageSize
86
     * @param string[] $orders
87
     * @param array    $conditions
88
     * @param array    $params
89
     *
90
     * @return Entity[]
91
     * @throws OrmException
92
     */
93
    public function getPage(int $limitFrom, int $pageSize, array $orders, array $conditions, array $params): array
94
    {
95
        $query = $this->getBaseQuery()
96
            ->limit($pageSize)
97
            ->offset($limitFrom);
98
99
        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...
100
            $query->orderBy('created_at ASC');
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 OrmException
123
     */
124
    public function getById($id)
125
    {
126
        $query = $this->getBaseQuery()->andWhere('ac.id = :api_client_id');
127
128
        $parameters = [
129
            'api_client_id' => [$id, \PDO::PARAM_STR],
130
        ];
131
132
        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) also could return the type array which is incompatible with the documented return type AbterPhp\Admin\Domain\Entities\ApiClient|null.
Loading history...
133
    }
134
135
    /**
136
     * @param IStringerEntity $entity
137
     *
138
     * @throws InvalidQueryException
139
     */
140
    public function update($entity)
141
    {
142
        assert($entity instanceof Entity, new \InvalidArgumentException());
143
144
        $query = (new QueryBuilder())
145
            ->update(
146
                'api_clients',
147
                'api_clients',
148
                [
149
                    'description' => [$entity->getDescription(), \PDO::PARAM_STR],
150
                    'secret'      => [$entity->getSecret(), \PDO::PARAM_STR],
151
                ]
152
            )
153
            ->where('id = ?')
154
            ->andWhere('deleted_at IS NULL')
155
            ->addUnnamedPlaceholderValue($entity->getId(), \PDO::PARAM_STR);
156
157
        $statement = $this->writeConnection->prepare($query->getSql());
158
        $statement->bindValues($query->getParameters());
159
        $statement->execute();
160
161
        $this->deleteAdminResources($entity);
162
        $this->addAdminResources($entity);
163
    }
164
165
    /**
166
     * @param array $hash
167
     *
168
     * @return Entity
169
     */
170
    protected function loadEntity(array $hash): Entity
171
    {
172
        $adminResources = $this->loadAdminResources($hash);
173
174
        return new Entity(
175
            $hash['id'],
176
            $hash['user_id'],
177
            $hash['description'],
178
            $hash['secret'],
179
            $adminResources
180
        );
181
    }
182
183
    /**
184
     * @param array $hash
185
     *
186
     * @return array
187
     */
188
    protected function loadAdminResources(array $hash): array
189
    {
190
        if (empty($hash['admin_resource_ids'])) {
191
            return [];
192
        }
193
194
        $adminResourceIds         = explode(',', $hash['admin_resource_ids']);
195
        $adminResourceIdentifiers = explode(',', $hash['admin_resource_identifiers']);
196
197
        $adminResources = [];
198
        foreach ($adminResourceIds as $idx => $adminResourceId) {
199
            $adminResources[] = new AdminResource($adminResourceId, $adminResourceIdentifiers[$idx]);
200
        }
201
202
        return $adminResources;
203
    }
204
205
    /**
206
     * @return SelectQuery
207
     */
208
    private function getBaseQuery(): SelectQuery
209
    {
210
        return (new QueryBuilder())
211
            ->select(
212
                'ac.id',
213
                'ac.user_id',
214
                'ac.description',
215
                'ac.secret',
216
                'GROUP_CONCAT(ar.id) AS admin_resource_ids',
217
                'GROUP_CONCAT(ar.identifier) AS admin_resource_identifiers'
218
            )
219
            ->from('api_clients', 'ac')
220
            ->leftJoin('api_clients_admin_resources', 'acar', 'acar.api_client_id = ac.id')
221
            ->leftJoin('admin_resources', 'ar', 'acar.admin_resource_id = ar.id')
222
            ->where('ac.deleted_at IS NULL')
223
            ->groupBy('ac.id');
224
    }
225
226
    /**
227
     * @param Entity $entity
228
     *
229
     * @throws InvalidQueryException
230
     */
231
    protected function deleteAdminResources(Entity $entity)
232
    {
233
        $query = (new QueryBuilder())
234
            ->delete('api_clients_admin_resources')
235
            ->where('api_client_id = ?')
236
            ->addUnnamedPlaceholderValue($entity->getId(), \PDO::PARAM_STR);
237
238
        $sql    = $query->getSql();
239
        $params = $query->getParameters();
240
241
        $statement = $this->writeConnection->prepare($sql);
242
        $statement->bindValues($params);
243
        $statement->execute();
244
    }
245
246
    /**
247
     * @param Entity $entity
248
     */
249
    protected function addAdminResources(Entity $entity)
250
    {
251
        $idGenerator = $this->getIdGenerator();
252
253
        foreach ($entity->getAdminResources() as $adminResource) {
254
            $query = (new QueryBuilder())
255
                ->insert(
256
                    'api_clients_admin_resources',
257
                    [
258
                        'id'                => [$idGenerator->generate($entity), \PDO::PARAM_STR],
259
                        'api_client_id'     => [$entity->getId(), \PDO::PARAM_STR],
260
                        'admin_resource_id' => [$adminResource->getId(), \PDO::PARAM_STR],
261
                    ]
262
                );
263
264
            $sql    = $query->getSql();
265
            $params = $query->getParameters();
266
267
            $statement = $this->writeConnection->prepare($sql);
268
            $statement->bindValues($params);
269
            $statement->execute();
270
        }
271
    }
272
}
273