Test Setup Failed
Push — master ( 29a8b0...da4e0b )
by Php Easy Api
03:15
created

Client   F

Complexity

Total Complexity 75

Size/Duplication

Total Lines 513
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 129
dl 0
loc 513
rs 2.4
c 0
b 0
f 0
wmc 75

19 Methods

Rating   Name   Duplication   Size   Complexity  
B generatorMethod() 0 34 8
A __construct() 0 13 2
A capsuleCaret() 0 17 5
A containerRegister() 0 5 1
A expectedInputs() 0 25 6
A except() 0 14 2
B autoValidate() 0 23 9
A checkProperties() 0 6 4
A capsule() 0 15 6
A generatorManager() 0 16 5
A checkHttpMethod() 0 16 3
A handle() 0 17 1
A getRequestData() 0 15 5
A registerRequestInputs() 0 13 1
A setClientObjects() 0 16 3
A initClient() 0 9 2
A requestProperties() 0 21 1
B setRequestInputs() 0 26 7
A validation() 0 7 4

How to fix   Complexity   

Complex Class

Complex classes like Client 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 Client, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Resta\Client;
4
5
use Resta\Support\Utils;
6
use Resta\Contracts\HandleContracts;
7
use Resta\Support\ReflectionProcess;
8
use ReflectionException as ReflectionExceptionAlias;
9
10
class Client extends ClientAbstract implements HandleContracts
11
{
12
    /**
13
     * @var array
14
     */
15
    protected $capsule = [];
16
17
    /**
18
     * @var array
19
     */
20
    protected $except = [];
21
22
    /**
23
     * @var string
24
     */
25
    protected $method;
26
27
    /**
28
     * @var ReflectionProcess
29
     */
30
    protected $reflection;
31
32
    /**
33
     * @var null|object
34
     */
35
    protected $requestHttp;
36
37
    /**
38
     * @var null|array
39
     */
40
    protected $clientData;
41
42
    /**
43
     * @var null|array
44
     */
45
    protected $requestData;
46
47
    /**
48
     * Request constructor.
49
     *
50
     * @param null|array $clientData
51
     *
52
     * @throws ReflectionExceptionAlias
53
     */
54
    public function __construct($clientData=null)
55
    {
56
        //reflection process
57
        $this->reflection = app()['reflection']($this);
58
59
        //get http method via request http manager class
60
        $this->requestHttp = app()->resolve(ClientHttpManager::class);
61
62
        //get request client data
63
        $this->clientData = ($clientData===null) ? $this->requestHttp->resolve() : $clientData;
64
65
        //handle request
66
        $this->handle();
67
    }
68
69
    /**
70
     * auto validate
71
     *
72
     * @param $validate
73
     */
74
    private function autoValidate($validate)
75
    {
76
        //we get the values ​​to auto-validate.
77
        foreach ($this->{$validate} as $object=>$datas){
78
79
            // the auto-validate value must necessarily represent a class.
80
            // otherwise auto-validate is not used.
81
            if(Utils::isNamespaceExists($object)){
82
                $getObjectInstance = app()->resolve($object);
83
84
                // we get the index values,
85
                // which are called methods of the auto-validate value that represents the class.
86
                foreach ($datas as $dataKey=>$data){
87
88
                    // if the methods of the auto-validate class resolved by the container resolve method apply,
89
                    // the process of auto-validate automatic implementation will be completed.
90
                    if(is_numeric($dataKey) && method_exists($getObjectInstance,$data)){
91
                        if(isset($this->origin[$data])){
92
                            if(!is_array($this->origin[$data])){
93
                                $this->origin[$data] = array($this->origin[$data]);
94
                            }
95
                            foreach ($this->origin[$data] as $originData){
96
                                $getObjectInstance->{$data}($originData);
97
                            }
98
                        }
99
                    }
100
                }
101
            }
102
        }
103
    }
104
105
    /**
106
     * capsule inputs
107
     *
108
     * @return void|mixed
109
     */
110
    private function capsule()
111
    {
112
        // expected method is executed.
113
        // this method is a must for http method values to be found in this property.
114
        if($this->checkProperties('capsule')){
115
116
            $caret = $this->capsuleCaret();
117
118
            foreach($this->inputs as $input=>$value){
119
120
                if(isset($caret[$input]) || (
121
                        $this->checkProperties('capsule') && !in_array($input,$this->capsule)
122
                    )){
123
                    exception('capsuleRequestException')
124
                        ->overflow('The '.$input.' value cannot be sent.');
125
                }
126
            }
127
        }
128
    }
129
130
    /**
131
     * get capsule caret for request
132
     *
133
     * @return array
134
     */
135
    private function capsuleCaret()
136
    {
137
        $caret = [];
138
139
        foreach($this->inputs as $input=>$item){
140
            if(in_array('@'.$input,$this->capsule)){
141
                $caret[$input] = $item;
142
            }
143
        }
144
145
        foreach ($this->capsule as $item) {
146
            if(preg_match('#@.*#is',$item)){
147
                $this->capsule = array_diff($this->capsule,[$item]);
148
            }
149
        }
150
151
        return $caret;
152
    }
153
154
    /**
155
     * check http method
156
     *
157
     * @return void|mixed
158
     */
159
    private function checkHttpMethod()
160
    {
161
        //get http method
162
        $method = $this->requestHttp->getMethod();
0 ignored issues
show
Bug introduced by
The method getMethod() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

162
        /** @scrutinizer ignore-call */ $method = $this->requestHttp->getMethod();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
163
164
        // Determines which HTTP method
165
        // the request object will be exposed to.
166
        if($this->checkProperties('http')){
167
168
            // if the current http method does not exist
169
            // in the http object, the exception will be thrown.
170
            if(!in_array($method,$this->http)){
0 ignored issues
show
Bug Best Practice introduced by
The property http does not exist on Resta\Client\Client. Did you maybe forget to declare it?
Loading history...
171
172
                //exception batMethodCall
173
                exception()->badMethodCall(
174
                    'Invalid http method process for '.class_basename($this).'.That is accepted http methods ['.implode(",",$this->http).'] ');
175
            }
176
        }
177
    }
178
179
    /**
180
     * check properties
181
     *
182
     * @param $properties
183
     * @return bool
184
     */
185
    private function checkProperties($properties)
186
    {
187
        // from the properties of the object properties to
188
        // the existing variables, control the array and at least one element.
189
        return (property_exists($this,$properties)
190
            && is_array($this->{$properties}) && count($this->{$properties})) ? true : false;
191
    }
192
193
    /**
194
     * register container for request
195
     *
196
     * @return mixed|void
197
     */
198
    private function containerRegister()
199
    {
200
        // we are saving the expected values ​​for the request in container.
201
        // this record can be returned in exception information.
202
        app()->register('requestExpected',$this->expected);
0 ignored issues
show
Bug Best Practice introduced by
The property expected does not exist on Resta\Client\Client. Did you maybe forget to declare it?
Loading history...
203
    }
204
205
    /**
206
     * get request except
207
     *
208
     * @param $except
209
     * @return $this
210
     */
211
    public function except($except)
212
    {
213
        // the except parameter is a callable value.
214
        if(is_callable($except)){
215
            $call = call_user_func_array($except,[$this]);
216
            $except = $call;
217
        }
218
219
        // except with the except exceptions property
220
        // and then assigning them to the inputs property.
221
        $this->except = array_merge($this->except,$except);
222
        $this->inputs = array_diff_key($this->inputs,array_flip($this->except));
223
224
        return $this;
225
    }
226
227
    /**
228
     * expected inputs
229
     *
230
     * @return void|mixed
231
     */
232
    private function expectedInputs()
233
    {
234
        // expected method is executed.
235
        // this method is a must for http method values to be found in this property.
236
        if($this->checkProperties('expected')){
237
238
            // if the expected values are not found in the inputs array,
239
            // the exception will be thrown.
240
            foreach ($this->expected as $expected){
0 ignored issues
show
Bug Best Practice introduced by
The property expected does not exist on Resta\Client\Client. Did you maybe forget to declare it?
Loading history...
241
242
                $expectedValues = [];
243
244
                // mandatory expected data for each key can be separated by | operator.
245
                // this is evaluated as "or".
246
                foreach($expectedData = explode("|",$expected) as $inputs){
247
                    if(!isset($this->inputs[$inputs])){
248
                        $expectedValues[] = $inputs;
249
                    }
250
                }
251
252
                // if the expectedData and expectedValues ​​
253
                // array are numerically equal to the expected key, the exception is thrown.
254
                if(count($expectedData)===count($expectedValues)){
255
                    exception($expected)
256
                        ->unexpectedValue('You absolutely have to send the value '.implode(" or ",$expectedValues).' for request object');
257
                }
258
            }
259
        }
260
    }
261
262
    /**
263
     * generator manager
264
     *
265
     * @throws ReflectionExceptionAlias
266
     */
267
    private function generatorManager()
268
    {
269
        // check the presence of the generator object
270
        // and operate the generator over this object.
271
        if($this->checkProperties('auto_generators')){
272
            $generators = $this->getAutoGenerators();
273
        }
274
275
        // check the presence of the generator object
276
        // and operate the generator over this object.
277
        if($this->checkProperties('generators')){
278
            $generators = array_merge(isset($generators) ? $generators: [],$this->getGenerators());
279
        }
280
281
        if(isset($generators)){
282
            $this->generatorMethod($generators);
283
        }
284
    }
285
286
    /**
287
     * generator method
288
     *
289
     * @param $generators
290
     *
291
     * @throws ReflectionExceptionAlias
292
     */
293
    private function generatorMethod($generators)
294
    {
295
        //generator array object
296
        foreach ($generators as $generator){
297
298
            //generator method name
299
            $generatorMethodName = $generator.'Generator';
300
301
            // if the generator method is present,
302
            // the fake value is assigned.
303
            if(method_exists($this,$generatorMethodName)){
304
305
                //fake registration
306
                if(!isset($this->inputs[$generator])){
307
                    $this->{$generator} = $this->{$generatorMethodName}();
308
                    $this->inputs[$generator] = $this->{$generatorMethodName}();
309
                }
310
                else {
311
312
                    if($this->checkProperties('auto_generators_dont_overwrite')
313
                        && in_array($generator,$this->getAutoGeneratorsDontOverwrite())){
314
                        $this->{$generator} = $this->{$generatorMethodName}();
315
                        $this->inputs[$generator] = $this->{$generatorMethodName}();
316
                    }
317
318
                    if($this->checkProperties('generators_dont_overwrite')
319
                        && in_array($generator,$this->getGeneratorsDontOverwrite())){
320
                        $this->{$generator} = $this->{$generatorMethodName}();
321
                        $this->inputs[$generator] = $this->{$generatorMethodName}();
322
                    }
323
324
                }
325
326
                $this->registerRequestInputs($generator);
327
            }
328
        }
329
    }
330
331
    /**
332
     * get real request data for client
333
     *
334
     * @return array
335
     */
336
    public function getRequestData()
337
    {
338
        $list = [];
339
340
        foreach ($this->requestData as $key=>$item) {
341
            if(property_exists($this,'requestExcept') && !in_array($key,$this->requestExcept)){
342
                $list[$key] = $item;
343
            }
344
345
            if(!property_exists($this,'requestExcept')){
346
                $list[$key] = $item;
347
            }
348
        }
349
350
        return $list;
351
    }
352
353
    /**
354
     * request handle
355
     *
356
     * @return mixed|void
357
     *
358
     * @throws ReflectionExceptionAlias
359
     */
360
    public function handle()
361
    {
362
        //set container for request
363
        $this->containerRegister();
364
365
        //we record the values ​​
366
        //that coming with the post.
367
        $this->initClient();
368
369
        // we update the input values ​​after
370
        // we receive and check the saved objects.
371
        $this->setClientObjects();
372
373
        // we add our user-side properties for the request object,
374
        // and on this we will set all the request object properties
375
        // that may be useful for the application.
376
        $this->requestProperties();
377
    }
378
379
    /**
380
     * get init client
381
     *
382
     * @return void
383
     */
384
    private function initClient()
385
    {
386
        // we use the http method to write
387
        // the values to the inputs and origin properties.
388
        foreach($this->clientData as $key=>$value){
389
390
            //inputs and origin properties
391
            $this->inputs[$key] = $value;
392
            $this->origin[$key] = $value;
393
        }
394
    }
395
396
    /**
397
     * request properties
398
     *
399
     * @throws ReflectionExceptionAlias
400
     */
401
    private function requestProperties()
402
    {
403
        // if a fake method is defined and it is not in
404
        // the context of any key method when access is granted,
405
        // it can be filled with fake method.
406
        $this->generatorManager();
407
408
        // contrary to capsule method,
409
        // expected values must be in the key being sent.
410
        $this->expectedInputs();
411
412
        // get capsule as mandatory values
413
        $this->capsule();
414
415
        // this method determines
416
        // how the request object will be requested,
417
        $this->checkHttpMethod();
418
419
        // it passes all keys that are sent through
420
        // a validation method on the user side.
421
        $this->validation();
422
    }
423
424
    /**
425
     * set client objects
426
     *
427
     * @throws ReflectionExceptionAlias
428
     */
429
    private function setClientObjects()
430
    {
431
        $clientObjects = $this->getClientObjects();
432
433
        // we update the input values ​​after
434
        // we receive and check the saved objects.
435
        foreach ($clientObjects as $key=>$value){
436
437
            if(isset($clientObjects['origin'][$key])){
438
439
                $this->{$key} = $clientObjects['origin'][$key];
440
                $this->inputs[$key] = $this->{$key};
441
442
                // the request update to be performed using
443
                // the method name to be used with the http method.
444
                $this->registerRequestInputs($key);
445
            }
446
        }
447
    }
448
449
    /**
450
     * register request inputs
451
     *
452
     * @param $key
453
     *
454
     * @throws ReflectionExceptionAlias
455
     */
456
    private function registerRequestInputs($key)
457
    {
458
        // the method name to be used with
459
        // the http method.
460
        $requestMethod = $this->requestHttp->getMethod().''.ucfirst($key);
461
462
        // the request update to be performed using
463
        // the method name to be used with the http method.
464
        $this->setRequestInputs($requestMethod,$key);
465
466
        // the request update to be performed using
467
        // the method name to be used without the http method.
468
        $this->setRequestInputs($key,$key);
469
    }
470
471
    /**
472
     * set request inputs
473
     *
474
     * @param $method
475
     * @param $key
476
     *
477
     * @throws ReflectionExceptionAlias
478
     */
479
    private function setRequestInputs($method,$key)
480
    {
481
        if(method_exists($this,$method) && $this->reflection->reflectionMethodParams($method)->isProtected){
482
483
            //check annotations for method
484
            $annotation = app()->resolve(ClientAnnotationManager::class,['request'=>$this]);
485
            $annotation->annotation($method,$key);
486
487
            if(isset($this->inputs[$key]) && is_array($this->inputs[$key])){
488
489
                $inputKeys = $this->inputs[$key];
490
491
                $this->inputs[$key] = [];
492
                foreach ($inputKeys as $input){
493
494
                    $this->{$key}               = $input;
495
                    $keyMethod                  = $this->{$method}();
496
                    $this->inputs[$key][]       = $keyMethod;
497
                    $this->requestData[$key][]  = $keyMethod;
498
                }
499
            }
500
            else{
501
                if(isset($this->inputs[$key])){
502
                    $keyMethod = $this->{$method}();
503
                    $this->inputs[$key] = $keyMethod;
504
                    $this->requestData[$key] = $keyMethod;
505
                }
506
507
            }
508
        }
509
    }
510
511
    /**
512
     * validation for request
513
     *
514
     * @return void
515
     */
516
    private function validation()
517
    {
518
        // the auto object validate property is the property
519
        // where all of your request values ​​are automatically validated.
520
        if(property_exists($this,'autoObjectValidate')
521
            && is_array($this->autoObjectValidate) && count($this->autoObjectValidate)){
522
            $this->autoValidate('autoObjectValidate');
523
        }
524
    }
525
}