Test Setup Failed
Push — master ( fc4d01...a29f2e )
by Php Easy Api
03:44
created

Client::getClientName()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

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

164
        /** @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...
165
166
        // Determines which HTTP method
167
        // the request object will be exposed to.
168
        if($this->checkProperties('http')){
169
170
            // if the current http method does not exist
171
            // in the http object, the exception will be thrown.
172
            if(!in_array($method,$this->http)){
0 ignored issues
show
Bug introduced by
$this->http of type Resta\Client\Client is incompatible with the type array expected by parameter $haystack of in_array(). ( Ignorable by Annotation )

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

172
            if(!in_array($method,/** @scrutinizer ignore-type */ $this->http)){
Loading history...
173
174
                //exception batMethodCall
175
                exception()->badMethodCall(
176
                    'Invalid http method process for '.basename($this).'.That is accepted http methods ['.implode(",",$this->http).'] ');
0 ignored issues
show
Bug introduced by
$this of type Resta\Client\Client is incompatible with the type string expected by parameter $path of basename(). ( Ignorable by Annotation )

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

176
                    'Invalid http method process for '.basename(/** @scrutinizer ignore-type */ $this).'.That is accepted http methods ['.implode(",",$this->http).'] ');
Loading history...
Bug introduced by
$this->http of type Resta\Client\Client is incompatible with the type array expected by parameter $pieces of implode(). ( Ignorable by Annotation )

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

176
                    'Invalid http method process for '.basename($this).'.That is accepted http methods ['.implode(",",/** @scrutinizer ignore-type */ $this->http).'] ');
Loading history...
177
            }
178
        }
179
    }
180
181
    /**
182
     * check properties
183
     *
184
     * @param $properties
185
     * @return bool
186
     */
187
    private function checkProperties($properties)
188
    {
189
        // from the properties of the object properties to
190
        // the existing variables, control the array and at least one element.
191
        return (property_exists($this,$properties)
192
            && is_array($this->{$properties}) && count($this->{$properties})) ? true : false;
193
    }
194
195
    /**
196
     * register container for request
197
     *
198
     * @return mixed|void
199
     */
200
    private function containerRegister()
201
    {
202
        // we are saving the expected values ​​for the request in container.
203
        // this record can be returned in exception information.
204
        app()->register('requestExpected',$this->expected);
205
    }
206
207
    /**
208
     * get request except
209
     *
210
     * @param $except
211
     * @return $this
212
     */
213
    public function except($except)
214
    {
215
        // the except parameter is a callable value.
216
        if(is_callable($except)){
217
            $call = call_user_func_array($except,[$this]);
218
            $except = $call;
219
        }
220
221
        // except with the except exceptions property
222
        // and then assigning them to the inputs property.
223
        $this->except = array_merge($this->except,$except);
224
        $this->inputs = array_diff_key($this->inputs,array_flip($this->except));
225
226
        return $this;
227
    }
228
229
    /**
230
     * expected inputs
231
     *
232
     * @return void|mixed
233
     */
234
    private function expectedInputs()
235
    {
236
        // expected method is executed.
237
        // this method is a must for http method values to be found in this property.
238
        if($this->checkProperties('expected')){
239
240
            // if the expected values are not found in the inputs array,
241
            // the exception will be thrown.
242
            foreach ($this->expected as $expected){
243
244
                $expectedValues = [];
245
246
                // mandatory expected data for each key can be separated by | operator.
247
                // this is evaluated as "or".
248
                foreach($expectedData = explode("|",$expected) as $inputs){
249
                    if(!isset($this->inputs[$inputs])){
250
                        $expectedValues[$inputs] = $inputs;
251
                    }
252
                }
253
254
                // if the expectedData and expectedValues ​​
255
                // array are numerically equal to the expected key, the exception is thrown.
256
                if(count($expectedData)===count($expectedValues)){
257
                    exception('clientExpected',['key'=>$expected])
258
                        ->unexpectedValue('You absolutely have to send the value '.implode(" or ",$expectedValues).' for request object');
259
                }
260
            }
261
        }
262
    }
263
264
    /**
265
     * generator manager
266
     *
267
     * @throws ReflectionExceptionAlias
268
     */
269
    private function generatorManager()
270
    {
271
        // check the presence of the generator object
272
        // and operate the generator over this object.
273
        if($this->checkProperties('auto_generators')){
274
            $generators = $this->getAutoGenerators();
275
        }
276
277
        // check the presence of the generator object
278
        // and operate the generator over this object.
279
        if($this->checkProperties('generators')){
280
            $generators = array_merge(isset($generators) ? $generators: [],$this->getGenerators());
0 ignored issues
show
Bug introduced by
It seems like $this->getGenerators() can also be of type Resta\Client\ClientAbstract; however, parameter $array2 of array_merge() does only seem to accept array|null, maybe add an additional type check? ( Ignorable by Annotation )

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

280
            $generators = array_merge(isset($generators) ? $generators: [],/** @scrutinizer ignore-type */ $this->getGenerators());
Loading history...
281
        }
282
283
        if(isset($generators)){
284
            $this->generatorMethod($generators);
285
        }
286
    }
287
288
    /**
289
     * generator method
290
     *
291
     * @param $generators
292
     *
293
     * @throws ReflectionExceptionAlias
294
     */
295
    private function generatorMethod($generators)
296
    {
297
        //generator array object
298
        foreach ($generators as $generator){
299
300
            //generator method name
301
            $generatorMethodName = $generator.'Generator';
302
303
            // if the generator method is present,
304
            // the fake value is assigned.
305
            if(method_exists($this,$generatorMethodName)){
306
307
                //fake registration
308
                if(!isset($this->inputs[$generator])){
309
310
                    $generatorMethodNameResult = $this->{$generatorMethodName}();
311
312
                    if(!is_null($generatorMethodNameResult)){
313
                        $this->{$generator} = $this->{$generatorMethodName}();
314
                        $this->inputs[$generator] = $this->{$generatorMethodName}();
315
                        $this->generatorList[] = $generator;
316
                    }
317
                }
318
                else {
319
320
                    if($this->checkProperties('auto_generators_dont_overwrite')
321
                        && in_array($generator,$this->getAutoGeneratorsDontOverwrite())){
0 ignored issues
show
Bug introduced by
It seems like $this->getAutoGeneratorsDontOverwrite() can also be of type Resta\Client\ClientAbstract; however, parameter $haystack of in_array() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

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

321
                        && in_array($generator,/** @scrutinizer ignore-type */ $this->getAutoGeneratorsDontOverwrite())){
Loading history...
322
                        $this->{$generator} = $this->{$generatorMethodName}();
323
                        $this->inputs[$generator] = $this->{$generatorMethodName}();
324
                        $this->generatorList[] = $generator;
325
                    }
326
327
                    if($this->checkProperties('generators_dont_overwrite')
328
                        && in_array($generator,$this->getGeneratorsDontOverwrite())){
329
                        $this->{$generator} = $this->{$generatorMethodName}();
330
                        $this->inputs[$generator] = $this->{$generatorMethodName}();
331
                        $this->generatorList[] = $generator;
332
                    }
333
334
                }
335
336
                $this->registerRequestInputs($generator);
337
            }
338
        }
339
    }
340
341
    /**
342
     * get client name for request
343
     *
344
     * @return string
345
     */
346
    public function getClientName()
347
    {
348
        return $this->clientName;
349
    }
350
351
    /**
352
     * request handle
353
     *
354
     * @return mixed|void
355
     *
356
     * @throws ReflectionExceptionAlias
357
     */
358
    public function handle()
359
    {
360
        //set container for request
361
        $this->containerRegister();
362
363
        //we record the values ​​
364
        //that coming with the post.
365
        $this->initClient();
366
367
        // this method determines
368
        // how the request object will be requested,
369
        $this->checkHttpMethod();
370
371
        // get capsule as mandatory values
372
        $this->capsule();
373
374
        // if a fake method is defined and it is not in
375
        // the context of any key method when access is granted,
376
        // it can be filled with fake method.
377
        $this->generatorManager();
378
379
        // contrary to capsule method,
380
        // expected values must be in the key being sent.
381
        $this->expectedInputs();
382
383
        // it passes all keys that are sent through
384
        // a validation method on the user side.
385
        $this->validation();
386
387
        // we update the input values ​​after
388
        // we receive and check the saved objects.
389
        $this->setClientObjects();
390
391
        // the values ​​specified in request except property
392
        // are subtracted from all input values.
393
        $this->requestExcept();
394
    }
395
396
    /**
397
     * get init client
398
     *
399
     * @return void
400
     */
401
    private function initClient()
402
    {
403
        // we use the http method to write
404
        // the values to the inputs and origin properties.
405
        foreach($this->clientData as $key=>$value){
406
407
            //inputs and origin properties
408
            $this->inputs[$key] = $value;
409
            $this->origin[$key] = $value;
410
        }
411
    }
412
413
    /**
414
     * the values ​​specified in request except property
415
     * are subtracted from all input values.
416
     *
417
     * @return mixed|void
418
     */
419
    private function requestExcept()
420
    {
421
        if(property_exists($this,'requestExcept') && is_array($this->requestExcept)){
0 ignored issues
show
introduced by
The condition is_array($this->requestExcept) is always false.
Loading history...
422
            foreach ($this->requestExcept as $item){
423
                if(isset($this->inputs[$item])){
424
                    unset($this->inputs[$item]);
425
                }
426
            }
427
        }
428
    }
429
430
    /**
431
     * set client name for client resolver
432
     *
433
     * @param null|string $clientName
434
     * @return void|mixed
435
     */
436
    public function setClientName($clientName=null)
437
    {
438
        if(!is_null($clientName) && is_string($clientName)){
439
            return $this->clientName = $clientName;
440
        }
441
442
        if(!is_null(Utils::trace(0)) && isset(Utils::trace(0)['object'])){
443
            $backTrace = Utils::trace(0)['object'];
444
445
            if(property_exists($backTrace,'clientName')){
446
                $this->clientName = $backTrace->clientName;
447
            }
448
        }
449
    }
450
451
    /**
452
     * set client objects
453
     *
454
     * @throws ReflectionExceptionAlias
455
     */
456
    private function setClientObjects()
457
    {
458
        $clientObjects = $this->getClientObjects();
459
460
        // we update the input values ​​after
461
        // we receive and check the saved objects.
462
        foreach ($clientObjects as $key=>$value){
463
464
            if(property_exists($this,'groups') && is_array($this->groups) && in_array($key,$this->groups)){
465
466
                $this->{$key} = $clientObjects['origin'][array_search($key,$this->groups)][$key];
467
                $this->inputs[$key] = $this->{$key};
468
469
                // the request update to be performed using
470
                // the method name to be used with the http method.
471
                $this->registerRequestInputs($key);
472
                unset($this->inputs[$key]);
473
            }
474
475
            if(!in_array($key,$this->generatorList) && isset($clientObjects['origin'][$key])){
476
477
                $this->{$key} = $clientObjects['origin'][$key];
478
                $this->inputs[$key] = $this->{$key};
479
480
                // the request update to be performed using
481
                // the method name to be used with the http method.
482
                $this->registerRequestInputs($key);
483
            }
484
        }
485
486
    }
487
488
    /**
489
     * register request inputs
490
     *
491
     * @param $key
492
     *
493
     * @throws ReflectionExceptionAlias
494
     */
495
    private function registerRequestInputs($key)
496
    {
497
        // the method name to be used with
498
        // the http method.
499
        $requestMethod = $this->requestHttp->getMethod().''.ucfirst($key);
500
501
        // the request update to be performed using
502
        // the method name to be used with the http method.
503
        $this->setRequestInputs($requestMethod,$key);
504
505
        // the request update to be performed using
506
        // the method name to be used without the http method.
507
        $this->setRequestInputs($key,$key);
508
    }
509
510
    /**
511
     * set request inputs
512
     *
513
     * @param $method
514
     * @param $key
515
     *
516
     * @throws ReflectionExceptionAlias
517
     */
518
    private function setRequestInputs($method,$key)
519
    {
520
        if(!in_array($key,$this->generatorList) && method_exists($this,$method) && $this->reflection->reflectionMethodParams($method)->isProtected){
521
522
            //check annotations for method
523
            $annotation = app()->resolve(ClientAnnotationManager::class,['request'=>$this]);
524
            $annotation->annotation($method,$key);
525
526
            if(isset($this->inputs[$key]) && is_array($this->inputs[$key])){
527
528
                $inputKeys = $this->inputs[$key];
529
530
                $this->inputs[$key] = [];
531
                foreach ($inputKeys as $input){
532
533
                    $this->{$key}               = $input;
534
                    $keyMethod                  = $this->{$method}();
535
                    $this->inputs[$key][]       = $keyMethod;
536
                }
537
            }
538
            else{
539
                if(isset($this->inputs[$key])){
540
                    $keyMethod = $this->{$method}();
541
                    $this->inputs[$key] = $keyMethod;
542
                }
543
544
            }
545
        }
546
    }
547
548
    /**
549
     * validation for request
550
     *
551
     * @return void
552
     */
553
    private function validation()
554
    {
555
        // the auto object validate property is the property
556
        // where all of your request values ​​are automatically validated.
557
        /** @noinspection PhpParamsInspection */
558
        if(property_exists($this,'autoObjectValidate')
559
            && is_array($this->autoObjectValidate) && count($this->autoObjectValidate)){
0 ignored issues
show
introduced by
The condition is_array($this->autoObjectValidate) is always false.
Loading history...
560
            $this->autoValidate('autoObjectValidate');
561
        }
562
    }
563
}