Test Setup Failed
Push — master ( d7ad2e...14e992 )
by Php Easy Api
04:20
created

Request::capsule()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 4
nc 4
nop 0
dl 0
loc 8
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Resta\Request;
4
5
use Resta\Support\Utils;
6
use Resta\Contracts\HandleContracts;
7
use Resta\Support\ReflectionProcess;
8
use ReflectionException as ReflectionExceptionAlias;
9
10
class Request extends RequestAbstract implements HandleContracts
11
{
12
    /**
13
     * @var array
14
     */
15
    protected $except = [];
16
17
    /**
18
     * @var string
19
     */
20
    protected $method;
21
22
    /**
23
     * @var ReflectionProcess
24
     */
25
    protected $reflection;
26
27
    /**
28
     * @var null|object
29
     */
30
    protected $requestHttp;
31
32
    /**
33
     * @var null|array
34
     */
35
    protected $clientData;
36
37
    /**
38
     * Request constructor.
39
     *
40
     * @param null|array $clientData
41
     *
42
     * @throws ReflectionExceptionAlias
43
     */
44
    public function __construct($clientData=null)
45
    {
46
        //reflection process
47
        $this->reflection = app()['reflection']($this);
48
49
        //get http method via request http manager class
50
        $this->requestHttp = app()->resolve(RequestHttpManager::class);
51
52
        //get request client data
53
        $this->clientData = ($clientData===null) ? $this->requestHttp->resolve() : $clientData;
54
55
        //handle request
56
        $this->handle();
57
    }
58
59
    /**
60
     * auto validate
61
     *
62
     * @param $validate
63
     */
64
    private function autoValidate($validate)
65
    {
66
        //we get the values ​​to auto-validate.
67
        foreach ($this->{$validate} as $object=>$datas){
68
69
            // the auto-validate value must necessarily represent a class.
70
            // otherwise auto-validate is not used.
71
            if(Utils::isNamespaceExists($object)){
72
                $getObjectInstance = app()->resolve($object);
73
74
                // we get the index values,
75
                // which are called methods of the auto-validate value that represents the class.
76
                foreach ($datas as $dataKey=>$data){
77
78
                    // if the methods of the auto-validate class resolved by the container resolve method apply,
79
                    // the process of auto-validate automatic implementation will be completed.
80
                    if(is_numeric($dataKey) && method_exists($getObjectInstance,$data)){
81
                        if(isset($this->origin[$data])){
82
                            if(!is_array($this->origin[$data])){
83
                                $this->origin[$data] = array($this->origin[$data]);
84
                            }
85
                            foreach ($this->origin[$data] as $originData){
86
                                $getObjectInstance->{$data}($originData);
87
                            }
88
                        }
89
                    }
90
                }
91
            }
92
        }
93
    }
94
95
    /**
96
     * capsule inputs
97
     *
98
     * @return void|mixed
99
     */
100
    private function capsule()
101
    {
102
        // expected method is executed.
103
        // this method is a must for http method values to be found in this property.
104
        if($this->checkProperties('capsule')){
105
            foreach($this->inputs as $input=>$value){
106
                if(!in_array($input,$this->capsule)){
0 ignored issues
show
Bug Best Practice introduced by
The property capsule does not exist on Resta\Request\Request. Did you maybe forget to declare it?
Loading history...
107
                    exception('capsuleRequestException')->overflow('The '.$input.' value cannot be sent.');
108
                }
109
            }
110
        }
111
    }
112
113
    /**
114
     * check http method
115
     *
116
     * @return void|mixed
117
     */
118
    private function checkHttpMethod()
119
    {
120
        //get http method
121
        $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

121
        /** @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...
122
123
        // Determines which HTTP method
124
        // the request object will be exposed to.
125
        if($this->checkProperties('http')){
126
127
            // if the current http method does not exist
128
            // in the http object, the exception will be thrown.
129
            if(!in_array($method,$this->http)){
130
131
                //exception batMethodCall
132
                exception()->badMethodCall(
133
                    'Invalid http method process for '.class_basename($this).'.That is accepted http methods ['.implode(",",$this->http).'] ');
134
            }
135
        }
136
    }
137
138
    /**
139
     * check properties
140
     *
141
     * @param $properties
142
     * @return bool
143
     */
144
    private function checkProperties($properties)
145
    {
146
        // from the properties of the object properties to
147
        // the existing variables, control the array and at least one element.
148
        return (property_exists($this,$properties)
149
            && is_array($this->{$properties}) && count($this->{$properties})) ? true : false;
150
    }
151
152
    /**
153
     * register container for request
154
     *
155
     * @return mixed|void
156
     */
157
    private function containerRegister()
158
    {
159
        // we are saving the expected values ​​for the request in container.
160
        // this record can be returned in exception information.
161
        app()->register('requestExpected',$this->expected);
162
    }
163
164
    /**
165
     * get request except
166
     *
167
     * @param $except
168
     * @return $this
169
     */
170
    public function except($except)
171
    {
172
        // the except parameter is a callable value.
173
        if(is_callable($except)){
174
            $call = call_user_func_array($except,[$this]);
175
            $except = $call;
176
        }
177
178
        // except with the except exceptions property
179
        // and then assigning them to the inputs property.
180
        $this->except = array_merge($this->except,$except);
181
        $this->inputs = array_diff_key($this->inputs,array_flip($this->except));
182
183
        return $this;
184
    }
185
186
    /**
187
     * expected inputs
188
     *
189
     * @return void|mixed
190
     */
191
    private function expectedInputs()
192
    {
193
        // expected method is executed.
194
        // this method is a must for http method values to be found in this property.
195
        if($this->checkProperties('expected')){
196
197
            // if the expected values are not found in the inputs array,
198
            // the exception will be thrown.
199
            foreach ($this->expected as $expected){
200
201
                $expectedValues = [];
202
203
                // mandatory expected data for each key can be separated by | operator.
204
                // this is evaluated as "or".
205
                foreach($expectedData = explode("|",$expected) as $inputs){
206
                    if(!isset($this->inputs[$inputs])){
207
                        $expectedValues[] = $inputs;
208
                    }
209
                }
210
211
                // if the expectedData and expectedValues ​​
212
                // array are numerically equal to the expected key, the exception is thrown.
213
                if(count($expectedData)===count($expectedValues)){
214
                    exception($expected)
215
                        ->unexpectedValue('You absolutely have to send the value '.implode(" or ",$expectedValues).' for request object');
216
                }
217
            }
218
        }
219
    }
220
221
    /**
222
     * generator manager
223
     *
224
     * @throws ReflectionExceptionAlias
225
     */
226
    private function generatorManager()
227
    {
228
        // check the presence of the generator object
229
        // and operate the generator over this object.
230
        if($this->checkProperties('auto_generators')){
231
            $generators = $this->getAutoGenerators();
232
        }
233
234
        // check the presence of the generator object
235
        // and operate the generator over this object.
236
        if($this->checkProperties('generators')){
237
            $generators = array_merge(isset($generators) ? $generators: [],$this->getGenerators());
238
        }
239
240
        if(isset($generators)){
241
            $this->generatorMethod($generators);
242
        }
243
    }
244
245
    /**
246
     * generator method
247
     *
248
     * @param $generators
249
     *
250
     * @throws ReflectionExceptionAlias
251
     */
252
    private function generatorMethod($generators)
253
    {
254
        //generator array object
255
        foreach ($generators as $generator){
256
257
            //generator method name
258
            $generatorMethodName = $generator.'Generator';
259
260
            // if the generator method is present,
261
            // the fake value is assigned.
262
            if(method_exists($this,$generatorMethodName)){
263
264
                //fake registration
265
                if(!isset($this->inputs[$generator])){
266
                    $this->{$generator} = $this->{$generatorMethodName}();
267
                    $this->inputs[$generator] = $this->{$generatorMethodName}();
268
                }
269
                else {
270
271
                    if($this->checkProperties('auto_generators_dont_overwrite')
272
                        && in_array($generator,$this->getAutoGeneratorsDontOverwrite())){
273
                        $this->{$generator} = $this->{$generatorMethodName}();
274
                        $this->inputs[$generator] = $this->{$generatorMethodName}();
275
                    }
276
277
                    if($this->checkProperties('generators_dont_overwrite')
278
                        && in_array($generator,$this->getGeneratorsDontOverwrite())){
279
                        $this->{$generator} = $this->{$generatorMethodName}();
280
                        $this->inputs[$generator] = $this->{$generatorMethodName}();
281
                    }
282
283
                }
284
285
                $this->registerRequestInputs($generator);
286
            }
287
        }
288
    }
289
290
    /**
291
     * request handle
292
     *
293
     * @return mixed|void
294
     *
295
     * @throws ReflectionExceptionAlias
296
     */
297
    public function handle()
298
    {
299
        //set container for request
300
        $this->containerRegister();
301
302
        //we record the values ​​
303
        //that coming with the post.
304
        $this->initClient();
305
306
        // we update the input values ​​after
307
        // we receive and check the saved objects.
308
        $this->setClientObjects();
309
310
        // we add our user-side properties for the request object,
311
        // and on this we will set all the request object properties
312
        // that may be useful for the application.
313
        $this->requestProperties();
314
    }
315
316
    /**
317
     * get init client
318
     *
319
     * @return void
320
     */
321
    private function initClient()
322
    {
323
        // we use the http method to write
324
        // the values to the inputs and origin properties.
325
        foreach($this->clientData as $key=>$value){
326
327
            //inputs and origin properties
328
            $this->inputs[$key] = $value;
329
            $this->origin[$key] = $value;
330
        }
331
    }
332
333
    /**
334
     * request properties
335
     *
336
     * @throws ReflectionExceptionAlias
337
     */
338
    private function requestProperties()
339
    {
340
        // if a fake method is defined and it is not in
341
        // the context of any key method when access is granted,
342
        // it can be filled with fake method.
343
        $this->generatorManager();
344
345
        // contrary to capsule method,
346
        // expected values must be in the key being sent.
347
        $this->expectedInputs();
348
349
        // get capsule as mandatory values
350
        $this->capsule();
351
352
        // this method determines
353
        // how the request object will be requested,
354
        $this->checkHttpMethod();
355
356
        // it passes all keys that are sent through
357
        // a validation method on the user side.
358
        $this->validation();
359
    }
360
361
    /**
362
     * set client objects
363
     *
364
     * @throws ReflectionExceptionAlias
365
     */
366
    private function setClientObjects()
367
    {
368
        $clientObjects = $this->getClientObjects();
369
370
        // we update the input values ​​after
371
        // we receive and check the saved objects.
372
        foreach ($clientObjects as $key=>$value){
373
374
            if(isset($clientObjects['origin'][$key])){
375
376
                $this->{$key} = $clientObjects['origin'][$key];
377
                $this->inputs[$key] = $this->{$key};
378
379
                // the request update to be performed using
380
                // the method name to be used with the http method.
381
                $this->registerRequestInputs($key);
382
            }
383
        }
384
    }
385
386
    /**
387
     * register request inputs
388
     *
389
     * @param $key
390
     *
391
     * @throws ReflectionExceptionAlias
392
     */
393
    private function registerRequestInputs($key)
394
    {
395
        // the method name to be used with
396
        // the http method.
397
        $requestMethod = $this->requestHttp->getMethod().''.ucfirst($key);
398
399
        // the request update to be performed using
400
        // the method name to be used with the http method.
401
        $this->setRequestInputs($requestMethod,$key);
402
403
        // the request update to be performed using
404
        // the method name to be used without the http method.
405
        $this->setRequestInputs($key,$key);
406
    }
407
408
    /**
409
     * set request inputs
410
     *
411
     * @param $method
412
     * @param $key
413
     *
414
     * @throws ReflectionExceptionAlias
415
     */
416
    private function setRequestInputs($method,$key)
417
    {
418
        if(method_exists($this,$method) && $this->reflection->reflectionMethodParams($method)->isProtected){
419
420
            //check annotations for method
421
            $annotation = app()->resolve(RequestAnnotationManager::class,['request'=>$this]);
422
            $annotation->annotation($method,$key);
423
424
            if(isset($this->inputs[$key]) && is_array($this->inputs[$key])){
425
426
                $inputKeys = $this->inputs[$key];
427
428
                $this->inputs[$key] = [];
429
                foreach ($inputKeys as $input){
430
431
                    $this->{$key}           = $input;
432
                    $keyMethod              = $this->{$method}();
433
                    $this->inputs[$key][]   = $keyMethod;
434
                }
435
            }
436
            else{
437
                if(isset($this->inputs[$key])){
438
                    $keyMethod = $this->{$method}();
439
                    $this->inputs[$key] = $keyMethod;
440
                }
441
442
            }
443
        }
444
    }
445
446
    /**
447
     * validation for request
448
     *
449
     * @return void
450
     */
451
    private function validation()
452
    {
453
        // the auto object validate property is the property
454
        // where all of your request values ​​are automatically validated.
455
        if(property_exists($this,'autoObjectValidate')
456
            && is_array($this->autoObjectValidate) && count($this->autoObjectValidate)){
457
            $this->autoValidate('autoObjectValidate');
458
        }
459
    }
460
}