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

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