user   B
last analyzed

Complexity

Total Complexity 49

Size/Duplication

Total Lines 398
Duplicated Lines 0 %

Importance

Changes 9
Bugs 0 Features 1
Metric Value
eloc 120
dl 0
loc 398
rs 8.48
c 9
b 0
f 1
wmc 49

23 Methods

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