Passed
Push — master ( a1a81a...636c38 )
by Php Easy Api
03:08
created

Request::expectedInputs()   A

Complexity

Conditions 6
Paths 8

Size

Total Lines 26
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 10
nc 8
nop 0
dl 0
loc 26
rs 9.2222
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
9
class Request extends RequestAbstract implements HandleContracts
10
{
11
    /**
12
     * @var array $except
13
     */
14
    protected $except = [];
15
16
    /**
17
     * @var string $capsule
18
     */
19
    protected $capsule;
20
21
    /**
22
     * @var string $method
23
     */
24
    protected $method;
25
26
    /**
27
     * @var ReflectionProcess $reflection
28
     */
29
    protected $reflection;
30
31
    /**
32
     * @var string $data
33
     */
34
    protected $requestHttp;
35
36
    /**
37
     * Request constructor.
38
     */
39
    public function __construct()
40
    {
41
        //reflection process
42
        $this->reflection = app()['reflection']($this);
43
44
        //get http method via request http manager class
45
        $this->requestHttp = app()->resolve(RequestHttpManager::class);
46
47
        //handle request
48
        $this->handle();
49
    }
50
51
    /**
52
     * @param $validate
53
     */
54
    private function autoValidate($validate)
55
    {
56
        //we get the values ​​to auto-validate.
57
        foreach ($this->{$validate} as $object=>$datas){
58
59
            // the auto-validate value must necessarily represent a class.
60
            // otherwise auto-validate is not used.
61
            if(Utils::isNamespaceExists($object)){
62
                $getObjectInstance = app()->resolve($object);
63
64
                // we get the index values,
65
                // which are called methods of the auto-validate value that represents the class.
66
                foreach ($datas as $dataKey=>$data){
67
68
                    // if the methods of the auto-validate class resolved by the container resolve method apply,
69
                    // the process of auto-validate automatic implementation will be completed.
70
                    if(is_numeric($dataKey) && method_exists($getObjectInstance,$data)){
71
                        if(isset($this->origin[$data])){
72
                            if(!is_array($this->origin[$data])){
73
                                $this->origin[$data] = array($this->origin[$data]);
74
                            }
75
                            foreach ($this->origin[$data] as $originData){
76
                                $getObjectInstance->{$data}($originData);
77
                            }
78
                        }
79
                    }
80
                }
81
            }
82
        }
83
    }
84
85
    /**
86
     * check http method
87
     *
88
     * @return void|mixed
89
     */
90
    private function checkHttpMethod()
91
    {
92
        //get http method
93
        $method = $this->requestHttp->getMethod();
94
95
        // Determines which HTTP method
96
        // the request object will be exposed to.
97
        if($this->checkProperties('http')){
98
99
            // if the current http method does not exist
100
            // in the http object, the exception will be thrown.
101
            if(!in_array($method,$this->http)){
102
103
                //exception batMethodCall
104
                exception()->badMethodCall(
105
                    'Invalid http method process for 
106
                    '.class_basename($this).'.That is accepted http methods ['.implode(",",$this->http).'] ');
107
            }
108
        }
109
    }
110
111
    /**
112
     * check properties
113
     *
114
     * @param $properties
115
     * @return bool
116
     */
117
    private function checkProperties($properties)
118
    {
119
        // from the properties of the object properties to
120
        // the existing variables, control the array and at least one element.
121
        return (property_exists($this,$properties)
122
            && is_array($this->{$properties}) && count($this->{$properties})) ? true : false;
123
    }
124
125
    /**
126
     * register container for request
127
     *
128
     * @return mixed|void
129
     */
130
    private function containerRegister()
131
    {
132
        // we are saving the expected values ​​for the request in container.
133
        // this record can be returned in exception information.
134
        app()->register('requestExpected',$this->expected);
135
    }
136
137
    /**
138
     * get request except
139
     *
140
     * @param $except
141
     * @return $this
142
     */
143
    public function except($except)
144
    {
145
        // the except parameter is a callable value.
146
        if(is_callable($except)){
147
            $call = call_user_func_array($except,[$this]);
148
            $except = $call;
149
        }
150
151
        // except with the except exceptions property
152
        // and then assigning them to the inputs property.
153
        $this->except = array_merge($this->except,$except);
154
        $this->inputs = array_diff_key($this->inputs,array_flip($this->except));
155
156
        return $this;
157
    }
158
159
    /**
160
     * expected inputs
161
     *
162
     * @return void|mixed
163
     */
164
    private function expectedInputs()
165
    {
166
        // expected method is executed.
167
        // this method is a must for http method values to be found in this property.
168
        if($this->checkProperties('expected')){
169
170
            // if the expected values are not found in the inputs array,
171
            // the exception will be thrown.
172
            foreach ($this->expected as $expected){
173
174
                $expectedValues = [];
175
176
                // mandatory expected data for each key can be separated by | operator.
177
                // this is evaluated as "or".
178
                foreach($expectedData = explode("|",$expected) as $inputs){
179
                    if(!isset($this->inputs[$inputs])){
180
                        $expectedValues[] = $inputs;
181
                    }
182
                }
183
184
                // if the expectedData and expectedValues ​​
185
                // array are numerically equal to the expected key, the exception is thrown.
186
                if(count($expectedData)===count($expectedValues)){
187
                    exception()
188
                        ->unexpectedValue('You absolutely have to send the value 
189
                        '.implode(" or ",$expectedValues).' for request object');
190
                }
191
            }
192
        }
193
    }
194
195
    /**
196
     * generator manager
197
     *
198
     * @return void|mixed
199
     */
200
    private function generatorManager()
201
    {
202
        // check the presence of the generator object
203
        // and operate the generator over this object.
204
        if($this->checkProperties('auto_generators')){
205
            $generators = $this->auto_generators;
0 ignored issues
show
Bug Best Practice introduced by
The property auto_generators does not exist on Resta\Request\Request. Did you maybe forget to declare it?
Loading history...
206
        }
207
208
        // check the presence of the generator object
209
        // and operate the generator over this object.
210
        if($this->checkProperties('generators')){
211
            $generators = array_merge(isset($generators) ? $generators: [],$this->generators);
0 ignored issues
show
Bug Best Practice introduced by
The property generators does not exist on Resta\Request\Request. Did you maybe forget to declare it?
Loading history...
212
        }
213
214
        if(isset($generators)){
215
            $this->generatorMethod($generators);
216
        }
217
    }
218
219
    /**
220
     * generator method
221
     *
222
     * @param $generators
223
     */
224
    private function generatorMethod($generators)
225
    {
226
        //generator array object
227
        foreach ($generators as $generator){
228
229
            //generator method name
230
            $generatorMethodName = $generator.'Generator';
231
232
            // if the generator method is present,
233
            // the fake value is assigned.
234
            if(method_exists($this,$generatorMethodName)){
235
236
                //fake registration
237
                if(!isset($this->inputs[$generator])){
238
                    $this->{$generator} = $this->{$generatorMethodName}();
239
                    $this->inputs[$generator] = $this->{$generatorMethodName}();
240
                }
241
                else {
242
243
                    if($this->checkProperties('auto_generators_dont_overwrite')
244
                        && in_array($generator,$this->auto_generators_dont_overwrite)){
0 ignored issues
show
Bug Best Practice introduced by
The property auto_generators_dont_overwrite does not exist on Resta\Request\Request. Did you maybe forget to declare it?
Loading history...
245
                        $this->{$generator} = $this->{$generatorMethodName}();
246
                        $this->inputs[$generator] = $this->{$generatorMethodName}();
247
                    }
248
249
                    if($this->checkProperties('generators_dont_overwrite')
250
                        && in_array($generator,$this->generators_dont_overwrite)){
0 ignored issues
show
Bug Best Practice introduced by
The property generators_dont_overwrite does not exist on Resta\Request\Request. Did you maybe forget to declare it?
Loading history...
251
                        $this->{$generator} = $this->{$generatorMethodName}();
252
                        $this->inputs[$generator] = $this->{$generatorMethodName}();
253
                    }
254
255
                }
256
257
                $this->registerRequestInputs($generator);
258
            }
259
        }
260
    }
261
262
    /**
263
     * request handle
264
     *
265
     * @return void
266
     */
267
    public function handle()
268
    {
269
        //set container for request
270
        $this->containerRegister();
271
272
        //we record the values ​​
273
        //that coming with the post.
274
        $this->initClient();
275
276
        // we update the input values ​​after
277
        // we receive and check the saved objects.
278
        $this->setClientObjects();
279
280
        // we add our user-side properties for the request object,
281
        // and on this we will set all the request object properties
282
        // that may be useful for the application.
283
        $this->requestProperties();
284
    }
285
286
    /**
287
     * get init client
288
     *
289
     * @return void
290
     */
291
    private function initClient()
292
    {
293
        // we use the http method to write
294
        // the values to the inputs and origin properties.
295
        foreach($this->requestHttp->resolve() as $key=>$value){
296
297
            //inputs and origin properties
298
            $this->inputs[$key] = $value;
299
            $this->origin[$key] = $value;
300
        }
301
    }
302
303
    /**
304
     * request properties
305
     *
306
     * @return void|mixed
307
     */
308
    private function requestProperties()
309
    {
310
        // if a fake method is defined and it is not in
311
        // the context of any key method when access is granted,
312
        // it can be filled with fake method.
313
        $this->generatorManager();
314
315
        // contrary to capsule method,
316
        // expected values must be in the key being sent.
317
        $this->expectedInputs();
318
319
        // this method determines
320
        // how the request object will be requested,
321
        $this->checkHttpMethod();
322
323
        // it passes all keys that are sent through
324
        // a validation method on the user side.
325
        $this->validation();
326
    }
327
328
    /**
329
     * set client objects
330
     *
331
     * @return mixed
332
     */
333
    private function setClientObjects()
334
    {
335
        $clientObjects = $this->getClientObjects();
336
337
        // we update the input values ​​after
338
        // we receive and check the saved objects.
339
        foreach ($clientObjects as $key=>$value){
340
341
            if(isset($clientObjects['origin'][$key])){
342
343
                $this->{$key} = $clientObjects['origin'][$key];
344
                $this->inputs[$key] = $this->{$key};
345
346
                // the request update to be performed using
347
                // the method name to be used with the http method.
348
                $this->registerRequestInputs($key);
349
            }
350
        }
351
    }
352
353
    /**
354
     * register request inputs
355
     *
356
     * @param $key
357
     */
358
    private function registerRequestInputs($key)
359
    {
360
        // the method name to be used with
361
        // the http method.
362
        $requestMethod = $this->requestHttp->getMethod().''.ucfirst($key);
363
364
        // the request update to be performed using
365
        // the method name to be used with the http method.
366
        $this->setRequestInputs($requestMethod,$key);
367
368
        // the request update to be performed using
369
        // the method name to be used without the http method.
370
        $this->setRequestInputs($key,$key);
371
    }
372
373
    /**
374
     * set request input
375
     *
376
     * @param $method
377
     * @param $key
378
     *
379
     * @throws \ReflectionException
380
     */
381
    private function setRequestInputs($method,$key)
382
    {
383
        if(method_exists($this,$method) && $this->reflection->reflectionMethodParams($method)->isProtected){
384
385
            //check annotations for method
386
            $annotation = app()->resolve(RequestAnnotationManager::class,['request'=>$this]);
387
            $annotation->annotation($method,$key);
388
389
            if(isset($this->inputs[$key]) && is_array($this->inputs[$key])){
390
391
                $inputKeys = $this->inputs[$key];
392
393
                $this->inputs[$key] = [];
394
                foreach ($inputKeys as $input){
395
396
                    $this->{$key}           = $input;
397
                    $keyMethod              = $this->{$method}();
398
                    $this->inputs[$key][]   = $keyMethod;
399
                }
400
            }
401
            else{
402
                if(isset($this->inputs[$key])){
403
                    $keyMethod = $this->{$method}();
404
                    $this->inputs[$key] = $keyMethod;
405
                }
406
407
            }
408
        }
409
    }
410
411
    /**
412
     * validation for request
413
     *
414
     * @return void
415
     */
416
    private function validation()
417
    {
418
        // the auto object validate property is the property
419
        // where all of your request values ​​are automatically validated.
420
        if(property_exists($this,'autoObjectValidate')
421
            && is_array($this->autoObjectValidate) && count($this->autoObjectValidate)){
422
            $this->autoValidate('autoObjectValidate');
423
        }
424
    }
425
}