Passed
Push — master ( 1d30f9...202808 )
by Peter
04:48
created

ApiClientSqlDataMapper   A

Complexity

Total Complexity 19

Size/Duplication

Total Lines 250
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 19
eloc 112
dl 0
loc 250
rs 10
c 0
b 0
f 0

11 Methods

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