user   B
last analyzed

Complexity

Total Complexity 51

Size/Duplication

Total Lines 409
Duplicated Lines 0 %

Importance

Changes 10
Bugs 0 Features 1
Metric Value
eloc 137
c 10
b 0
f 1
dl 0
loc 409
rs 7.92
wmc 51

23 Methods

Rating   Name   Duplication   Size   Complexity  
A load() 0 5 1
A credentials() 0 16 3
A update() 0 3 1
A create() 0 5 1
A getAccountID() 0 3 1
A timeNow() 0 4 1
A setAccountID() 0 4 1
A getOptions() 0 3 1
A validateName() 0 8 3
A getBucketToken() 0 3 1
B checkUpdateProperties() 0 11 7
A getDefaults() 0 5 1
A updateAccount() 0 17 2
A validate() 0 17 4
A buildUpdateSet() 0 27 4
A updateAccountAccess() 0 16 4
A checkVal() 0 9 4
A getJWT() 0 12 1
A validateMail() 0 8 3
A DB() 0 18 4
A updateAccess() 0 16 1
A setOptions() 0 4 1
A setBucketToken() 0 4 1

How to fix   Complexity   

Complex Class

Complex classes like user often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use user, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/**
4
 * ==================================
5
 * Responsible PHP API
6
 * ==================================
7
 *
8
 * @link Git https://github.com/vince-scarpa/responsibleAPI.git
9
 *
10
 * @api Responible API
11
 * @package responsible\core\user
12
 *
13
 * @author Vince scarpa <[email protected]>
14
 *
15
 */
16
17
namespace responsible\core\user;
18
19
use responsible\core\auth;
20
use responsible\core\configuration;
21
use responsible\core\connect;
22
use responsible\core\exception;
23
use responsible\core\headers;
24
25
class user
26
{
27
    /**
28
     * [$DB Data base object]
29
     * @var object
30
     */
31
    private $DB;
32
33
    /**
34
     * [$name Account username]
35
     * @var string
36
     */
37
    private $name;
38
39
    /**
40
     * [$name Account email address]
41
     * @var string
42
     */
43
    private $mail;
44
45
    /**
46
     * [$ACCOUNT_ID]
47
     * @var string
48
     */
49
    private $ACCOUNT_ID;
50
51
    /**
52
     * [$timestamp Time now]
53
     * @var integer
54
     */
55
    protected $timestamp;
56
57
    /**
58
     * [$bucketToken]
59
     * @var string
60
     */
61
    private $bucketToken;
62
63
    /**
64
     * [$options Resposible API options]
65
     * @var array
66
     */
67
    protected $options;
68
69
    /**
70
     * [$credentials User credentials]
71
     * @var array
72
     */
73
    protected $credentials;
74
75
    /**
76
     * [create Create a new access account]
77
     * @return array
78
     */
79
    public function create()
80
    {
81
        return (new userCreate($this->credentials))
82
            ->setOptions($this->getOptions())
83
            ->createAccount()
84
        ;
85
    }
86
87
    /**
88
     * [update Update an access account]
89
     * @return array
90
     */
91
    public function update($properties)
92
    {
93
        return $this->updateAccount($properties);
94
    }
95
96
    /**
97
     * [load Load a stored account]
98
     * @return array
99
     */
100
    public function load($property, array $options)
101
    {
102
        return (new userLoad($property, $options))
103
            ->setOptions($this->getOptions())
104
            ->account()
105
        ;
106
    }
107
108
    /**
109
     * [updateAccountAccess Update the requests account access]
110
     * @return void
111
     */
112
    public function updateAccountAccess($ACCOUNT_ID = null)
113
    {
114
        if (is_null($ACCOUNT_ID) && empty($this->ACCOUNT_ID)) {
115
            (new exception\errorException())
116
                ->message('No ACCOUNT_ID provided!')
117
                ->error('ACCOUNT_ID');
118
        }
119
120
        if (!is_null($ACCOUNT_ID)) {
121
            $this->setAccountID($ACCOUNT_ID);
122
        }
123
124
        /**
125
         * Upate the users access
126
         */
127
        $this->updateAccess();
128
    }
129
130
    /**
131
     * [updateAccess Update access for limit requests]
132
     * @return boolean
133
     */
134
    private function updateAccess()
135
    {
136
        return $this->DB()->
137
            query(
138
                "
139
                UPDATE responsible_api_users USR
140
                        JOIN responsible_token_bucket TKN
141
                            ON (USR.account_id = TKN.account_id)
142
                        set
143
                            USR.access = :unix,
144
                            TKN.bucket = :bkt
145
                        WHERE USR.account_id = :aid;",
146
                array(
147
                'unix' => (new \DateTime('now'))->getTimestamp(),
148
                'aid' => $this->getAccountID(),
149
                'bkt' => $this->getBucketToken(),
150
                )
151
            );
152
    }
153
154
    /**
155
     * [updateAccount Update access for limit requests]
156
     * @return mixed
157
     */
158
    private function updateAccount($properties)
159
    {
160
        if (is_array($properties)) {
161
            $properties = (object) $properties;
162
        }
163
164
        $this->checkUpdateProperties($properties);
165
166
        $updateSet = $this->buildUpdateSet($properties);
167
168
        return $this->DB()->query(
169
            "
170
            UPDATE responsible_api_users USR
171
                        set {$updateSet['set']}
172
                        WHERE {$updateSet['where']}
173
                ;",
174
            $updateSet['binds']
175
        );
176
    }
177
178
    /**
179
     * [checkUpdateProperties Check if we have the correct update properties]
180
     * @param  object $properties
181
     * @return void
182
     */
183
    private function checkUpdateProperties($properties)
184
    {
185
        if (
186
            !isset($properties->update) ||
187
            !isset($properties->where) ||
188
            (isset($properties->update) && !is_array($properties->update)) ||
189
            (isset($properties->where) && !is_array($properties->where))
190
        ) {
191
            (new exception\errorException())
192
                ->message('No update property was provided. Please read the documentation on updating user accounts.')
193
                ->error('ACCOUNT_UPDATE');
194
        }
195
    }
196
197
    /**
198
     * [buildUpdateSet description]
199
     * @param  object $properties
200
     * @return array
201
     */
202
    private function buildUpdateSet($properties)
203
    {
204
        $allowedFileds = $binds = [];
205
        $set = '';
206
207
        $columns = $this->DB()->query("SHOW COLUMNS FROM responsible_api_users");
208
209
        foreach ($columns as $f => $field) {
210
            $allowedFileds[] = $field['Field'];
211
        }
212
213
        foreach ($properties->update as $u => $update) {
214
            if (!in_array($u, $allowedFileds)) {
215
                unset($properties->update[$u]);
216
            } else {
217
                $set .= $u . ' = :' . $u . ',';
218
                $binds[$u] = $update;
219
            }
220
        }
221
222
        $set = rtrim($set, ',');
223
        $where = key($properties->where) . ' = ' . $properties->where[key($properties->where)];
224
225
        return [
226
            'set' => $set,
227
            'where' => $where,
228
            'binds' => $binds,
229
        ];
230
    }
231
232
    /**
233
     * [credentials Set the new account credentials]
234
     * @param  string $name
235
     *         username
236
     * @param  string $mail
237
     *         email address
238
     */
239
    public function credentials($name, $mail)
240
    {
241
        if (!$this->validate('name', $name) || !$this->validate('mail', $mail)) {
242
            (new exception\errorException())
243
                ->message(
244
                    'Username or email address validation error! Username must be a string and email must be valid.'
245
                )
246
                ->error('APPLICATION_ERROR');
247
        }
248
249
        $this->credentials = [
250
            'name' => $this->name,
251
            'mail' => $this->mail,
252
        ];
253
254
        return $this;
255
    }
256
257
    /**
258
     * [validate - Validate the new account credentials]
259
     * @return boolean
260
     */
261
    private function validate($type, $property)
262
    {
263
        $options = $this->getOptions();
264
        $valid = false;
265
        $skipValidatation = (isset($options['validate']) && $options['validate'] == false);
266
267
        switch ($type) {
268
            case 'name':
269
                $valid = $this->validateName($property, $skipValidatation);
270
                break;
271
272
            case 'mail':
273
                $valid = $this->validateMail($property, $skipValidatation);
274
                break;
275
        }
276
277
        return $valid;
278
    }
279
280
281
    private function validateName($property, $skipValidatation)
282
    {
283
        if (!is_string($property) && !$skipValidatation) {
284
            return false;
285
        }
286
        $this->name = preg_replace('/\s+/', '-', strtolower($property));
287
288
        return true;
289
    }
290
291
    private function validateMail($property, $skipValidatation)
292
    {
293
        if (!filter_var($property, FILTER_VALIDATE_EMAIL) && !$skipValidatation) {
294
            return false;
295
        }
296
        $this->mail = $property;
297
298
        return true;
299
    }
300
301
    /**
302
     * [getJWT Get the JWT payload]
303
     * @return array
304
     */
305
    protected function getJWT($key)
306
    {
307
        $token = (new headers\header())->authorizationHeaders(true);
308
        $jwt = new auth\jwt();
309
        $decoded = $jwt->token($token)
310
            ->key($key)
311
            ->decode()
312
        ;
313
314
        return [
315
            'token' => $token,
316
            'payload' => $decoded,
317
        ];
318
    }
319
320
    /**
321
     * [DB Get DB object]
322
     */
323
    protected function DB()
324
    {
325
        if (($this->options['db'] ?? null) && $this->options['db'] instanceof \responsible\core\connect\DB) {
326
            return $this->options['db'];
327
        }
328
329
        if (is_null($this->DB)) {
330
            $defaults = $this->getDefaults();
331
            $config = $defaults['config'];
332
333
            $this->DB = new connect\DB(
334
                $config['DB_HOST'],
335
                $config['DB_NAME'],
336
                $config['DB_USER'],
337
                $config['DB_PASSWORD']
338
            );
339
        }
340
        return $this->DB;
341
    }
342
343
    /**
344
     * [getDefaults Get the Responsible API defaults ]
345
     * @return array
346
     */
347
    protected function getDefaults()
348
    {
349
        $config = new configuration\config();
350
        $config->responsibleDefault();
351
        return $config->getDefaults();
352
    }
353
354
    /**
355
     * [setOptions Set the REsponsible API options]
356
     * @param array $options
357
     */
358
    public function setOptions($options)
359
    {
360
        $this->options = $options;
361
        return $this;
362
    }
363
364
    /**
365
     * [getOptions Get the Responsible API options]
366
     * @return array
367
     */
368
    protected function getOptions()
369
    {
370
        return $this->options;
371
    }
372
373
    /**
374
     * [timeNow Create a timestamp of now]
375
     * @return integer
376
     */
377
    protected function timeNow()
378
    {
379
        $this->timestamp = (new \DateTime('now'))->getTimestamp();
380
        return $this->timestamp;
381
    }
382
383
    /**
384
     * [setAccountID]
385
     */
386
    public function setAccountID($ACCOUNT_ID)
387
    {
388
        $this->ACCOUNT_ID = $ACCOUNT_ID;
389
        return $this;
390
    }
391
392
    /**
393
     * [getAccountID]
394
     * @return string
395
     */
396
    protected function getAccountID()
397
    {
398
        return $this->ACCOUNT_ID;
399
    }
400
401
    /**
402
     * [setBucket Bucket data token]
403
     * @param string $packed
404
     */
405
    public function setBucketToken($packed)
406
    {
407
        $this->bucketToken = $packed;
408
        return $this;
409
    }
410
411
    /**
412
     * [getBucketToken Bucket data token]
413
     * @param string $packed
414
     */
415
    public function getBucketToken()
416
    {
417
        return $this->bucketToken;
418
    }
419
420
    /**
421
     * [getClaim Check if a claim is set and not empty]
422
     * @param  string $claim
423
     * @return mixed
424
     */
425
    public function checkVal($option, $key, $default = false)
426
    {
427
        $val = isset($option[$key]) ? $option[$key] : $default;
428
429
        if ($val && empty($option[$key])) {
430
            $val = $default;
431
        }
432
433
        return $val;
434
    }
435
}
436