Completed
Push — master ( db46be...6b1c50 )
by Marcel
02:26
created

AbstractGenerator::prepareMiddleware()

Size

Total Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 1
nc 1
1
<?php
2
3
namespace Mpociot\ApiDoc\Generators;
4
5
use Faker\Factory;
6
use ReflectionClass;
7
use Illuminate\Support\Arr;
8
use Illuminate\Support\Str;
9
use Mpociot\Reflection\DocBlock;
10
use Mpociot\Reflection\DocBlock\Tag;
11
use Illuminate\Support\Facades\Validator;
12
use Illuminate\Foundation\Http\FormRequest;
13
use Mpociot\ApiDoc\Parsers\RuleDescriptionParser as Description;
14
15
abstract class AbstractGenerator
16
{
17
    /**
18
     * @param $route
19
     *
20
     * @return mixed
21
     */
22
    abstract public function getUri($route);
23
24
    /**
25
     * @param $route
26
     *
27
     * @return mixed
28
     */
29
    abstract public function getMethods($route);
30
31
    /**
32
     * @param  \Illuminate\Routing\Route $route
33
     * @param array $bindings
34
     * @param bool $withResponse
35
     *
36
     * @return array
37
     */
38
    abstract public function processRoute($route, $bindings = [], $withResponse = true);
39
40
    /**
41
     * Prepares / Disables route middlewares.
42
     *
43
     * @param  bool $disable
44
     *
45
     * @return  void
46
     */
47
    abstract public function prepareMiddleware($disable = false);
48
49
    /**
50
     * Get the response from the docblock if available.
51
     *
52
     * @param array $tags
53
     *
54
     * @return mixed
55
     */
56
    protected function getDocblockResponse($tags)
57
    {
58
        $responseTags = array_filter($tags, function ($tag) {
59
            if (! ($tag instanceof Tag)) {
60
                return false;
61
            }
62
63
            return \strtolower($tag->getName()) == 'response';
64
        });
65
        if (empty($responseTags)) {
66
            return;
67
        }
68
        $responseTag = \array_first($responseTags);
69
70
        return \response(\json_encode($responseTag->getContent()));
71
    }
72
73
    /**
74
     * @param array $routeData
75
     * @param array $routeAction
76
     * @param array $bindings
77
     *
78
     * @return mixed
79
     */
80
    protected function getParameters($routeData, $routeAction, $bindings)
81
    {
82
        $validator = Validator::make([], $this->getRouteRules($routeAction['uses'], $bindings));
83
        foreach ($validator->getRules() as $attribute => $rules) {
84
            $attributeData = [
85
                'required' => false,
86
                'type' => null,
87
                'default' => '',
88
                'value' => '',
89
                'description' => [],
90
            ];
91
            foreach ($rules as $ruleName => $rule) {
92
                $this->parseRule($rule, $attribute, $attributeData, $routeData['id']);
93
            }
94
            $routeData['parameters'][$attribute] = $attributeData;
95
        }
96
97
        return $routeData;
98
    }
99
100
    /**
101
     * @param  $route
102
     * @param  $bindings
103
     * @param  $headers
104
     *
105
     * @return \Illuminate\Http\Response
106
     */
107
    protected function getRouteResponse($route, $bindings, $headers = [])
108
    {
109
        $uri = $this->addRouteModelBindings($route, $bindings);
110
111
        $methods = $this->getMethods($route);
112
113
        // Split headers into key - value pairs
114
        $headers = collect($headers)->map(function ($value) {
115
            $split = explode(':', $value);
116
117
            return [trim($split[0]) => trim($split[1])];
118
        })->collapse()->toArray();
119
120
        //Changes url with parameters like /users/{user} to /users/1
121
        $uri = preg_replace('/{(.*?)}/', 1, $uri);
122
123
        return $this->callRoute(array_shift($methods), $uri, [], [], [], $headers);
0 ignored issues
show
Bug introduced by
It seems like $uri defined by preg_replace('/{(.*?)}/', 1, $uri) on line 121 can also be of type array<integer,string>; however, Mpociot\ApiDoc\Generator...tGenerator::callRoute() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
124
    }
125
126
    /**
127
     * @param $route
128
     * @param array $bindings
129
     *
130
     * @return mixed
131
     */
132
    protected function addRouteModelBindings($route, $bindings)
133
    {
134
        $uri = $this->getUri($route);
135
        foreach ($bindings as $model => $id) {
136
            $uri = str_replace('{'.$model.'}', $id, $uri);
137
        }
138
139
        return $uri;
140
    }
141
142
    /**
143
     * @param  \Illuminate\Routing\Route  $route
144
     *
145
     * @return string
146
     */
147
    protected function getRouteDescription($route)
148
    {
149
        list($class, $method) = explode('@', $route);
150
        $reflection = new ReflectionClass($class);
151
        $reflectionMethod = $reflection->getMethod($method);
152
153
        $comment = $reflectionMethod->getDocComment();
154
        $phpdoc = new DocBlock($comment);
155
156
        return [
157
            'short' => $phpdoc->getShortDescription(),
158
            'long' => $phpdoc->getLongDescription()->getContents(),
159
            'tags' => $phpdoc->getTags(),
160
        ];
161
    }
162
163
    /**
164
     * @param  string  $route
165
     *
166
     * @return string
167
     */
168
    protected function getRouteGroup($route)
169
    {
170
        list($class, $method) = explode('@', $route);
0 ignored issues
show
Unused Code introduced by
The assignment to $method is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
171
        $reflection = new ReflectionClass($class);
172
        $comment = $reflection->getDocComment();
173
        if ($comment) {
174
            $phpdoc = new DocBlock($comment);
175
            foreach ($phpdoc->getTags() as $tag) {
176
                if ($tag->getName() === 'resource') {
177
                    return $tag->getContent();
178
                }
179
            }
180
        }
181
182
        return 'general';
183
    }
184
185
    /**
186
     * @param  $route
187
     * @param  array $bindings
188
     *
189
     * @return array
190
     */
191
    protected function getRouteRules($route, $bindings)
192
    {
193
        list($class, $method) = explode('@', $route);
194
        $reflection = new ReflectionClass($class);
195
        $reflectionMethod = $reflection->getMethod($method);
196
197
        foreach ($reflectionMethod->getParameters() as $parameter) {
198
            $parameterType = $parameter->getClass();
199
            if (! is_null($parameterType) && class_exists($parameterType->name)) {
200
                $className = $parameterType->name;
201
202
                if (is_subclass_of($className, FormRequest::class)) {
0 ignored issues
show
Bug introduced by
Due to PHP Bug #53727, is_subclass_of might return inconsistent results on some PHP versions if \Illuminate\Foundation\Http\FormRequest::class can be an interface. If so, you could instead use ReflectionClass::implementsInterface.
Loading history...
203
                    $parameterReflection = new $className;
204
                    // Add route parameter bindings
205
                    $parameterReflection->query->add($bindings);
206
                    $parameterReflection->request->add($bindings);
207
208
                    if (method_exists($parameterReflection, 'validator')) {
209
                        return $parameterReflection->validator()->getRules();
210
                    } else {
211
                        return $parameterReflection->rules();
212
                    }
213
                }
214
            }
215
        }
216
217
        return [];
218
    }
219
220
    /**
221
     * @param  array  $arr
222
     * @param  string  $first
223
     * @param  string  $last
224
     *
225
     * @return string
226
     */
227
    protected function fancyImplode($arr, $first, $last)
228
    {
229
        $arr = array_map(function ($value) {
230
            return '`'.$value.'`';
231
        }, $arr);
232
        array_push($arr, implode($last, array_splice($arr, -2)));
233
234
        return implode($first, $arr);
235
    }
236
237
    protected function splitValuePairs($parameters, $first = 'is ', $last = 'or ')
238
    {
239
        $attribute = '';
240
        collect($parameters)->map(function ($item, $key) use (&$attribute, $first, $last) {
241
            $attribute .= '`'.$item.'` ';
242
            if (($key + 1) % 2 === 0) {
243
                $attribute .= $last;
244
            } else {
245
                $attribute .= $first;
246
            }
247
        });
248
        $attribute = rtrim($attribute, $last);
249
250
        return $attribute;
251
    }
252
253
    /**
254
     * @param  string  $rule
255
     * @param  string  $ruleName
256
     * @param  array  $attributeData
257
     * @param  int  $seed
258
     *
259
     * @return void
260
     */
261
    protected function parseRule($rule, $ruleName, &$attributeData, $seed)
262
    {
263
        $faker = Factory::create();
264
        $faker->seed(crc32($seed));
265
266
        $parsedRule = $this->parseStringRule($rule);
267
        $parsedRule[0] = $this->normalizeRule($parsedRule[0]);
268
        list($rule, $parameters) = $parsedRule;
269
270
        switch ($rule) {
271
            case 'required':
272
                $attributeData['required'] = true;
273
                break;
274
            case 'accepted':
275
                $attributeData['required'] = true;
276
                $attributeData['type'] = 'boolean';
277
                $attributeData['value'] = true;
278
                break;
279 View Code Duplication
            case 'after':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
280
                $attributeData['type'] = 'date';
281
                $attributeData['description'][] = Description::parse($rule)->with(date(DATE_RFC850, strtotime($parameters[0])))->getDescription();
282
                $attributeData['value'] = date(DATE_RFC850, strtotime('+1 day', strtotime($parameters[0])));
283
                break;
284 View Code Duplication
            case 'alpha':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
285
                $attributeData['description'][] = Description::parse($rule)->getDescription();
286
                $attributeData['value'] = $faker->word;
287
                break;
288
            case 'alpha_dash':
289
                $attributeData['description'][] = Description::parse($rule)->getDescription();
290
                break;
291
            case 'alpha_num':
292
                $attributeData['description'][] = Description::parse($rule)->getDescription();
293
                break;
294 View Code Duplication
            case 'in':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
295
                $attributeData['description'][] = Description::parse($rule)->with($this->fancyImplode($parameters, ', ', ' or '))->getDescription();
296
                $attributeData['value'] = $faker->randomElement($parameters);
297
                break;
298 View Code Duplication
            case 'not_in':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
299
                $attributeData['description'][] = Description::parse($rule)->with($this->fancyImplode($parameters, ', ', ' or '))->getDescription();
300
                $attributeData['value'] = $faker->word;
301
                break;
302 View Code Duplication
            case 'min':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
303
                $attributeData['description'][] = Description::parse($rule)->with($parameters)->getDescription();
304
                if (Arr::get($attributeData, 'type') === 'numeric' || Arr::get($attributeData, 'type') === 'integer') {
305
                    $attributeData['value'] = $faker->numberBetween($parameters[0]);
306
                }
307
                break;
308 View Code Duplication
            case 'max':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
309
                $attributeData['description'][] = Description::parse($rule)->with($parameters)->getDescription();
310
                if (Arr::get($attributeData, 'type') === 'numeric' || Arr::get($attributeData, 'type') === 'integer') {
311
                    $attributeData['value'] = $faker->numberBetween(0, $parameters[0]);
312
                }
313
                break;
314
            case 'between':
315
                if (! isset($attributeData['type'])) {
316
                    $attributeData['type'] = 'numeric';
317
                }
318
                $attributeData['description'][] = Description::parse($rule)->with($parameters)->getDescription();
319
                $attributeData['value'] = $faker->numberBetween($parameters[0], $parameters[1]);
320
                break;
321 View Code Duplication
            case 'before':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
322
                $attributeData['type'] = 'date';
323
                $attributeData['description'][] = Description::parse($rule)->with(date(DATE_RFC850, strtotime($parameters[0])))->getDescription();
324
                $attributeData['value'] = date(DATE_RFC850, strtotime('-1 day', strtotime($parameters[0])));
325
                break;
326
            case 'date_format':
327
                $attributeData['type'] = 'date';
328
                $attributeData['description'][] = Description::parse($rule)->with($parameters)->getDescription();
329
                $attributeData['value'] = date($parameters[0]);
330
                break;
331
            case 'different':
332
                $attributeData['description'][] = Description::parse($rule)->with($parameters)->getDescription();
333
                break;
334
            case 'digits':
335
                $attributeData['type'] = 'numeric';
336
                $attributeData['description'][] = Description::parse($rule)->with($parameters)->getDescription();
337
                $attributeData['value'] = ($parameters[0] < 9) ? $faker->randomNumber($parameters[0], true) : substr(mt_rand(100000000, mt_getrandmax()), 0, $parameters[0]);
338
                break;
339
            case 'digits_between':
340
                $attributeData['type'] = 'numeric';
341
                $attributeData['description'][] = Description::parse($rule)->with($parameters)->getDescription();
342
                break;
343 View Code Duplication
            case 'file':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
344
                $attributeData['type'] = 'file';
345
                $attributeData['description'][] = Description::parse($rule)->getDescription();
346
                break;
347 View Code Duplication
            case 'image':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
348
                $attributeData['type'] = 'image';
349
                $attributeData['description'][] = Description::parse($rule)->getDescription();
350
                break;
351
            case 'json':
352
                $attributeData['type'] = 'string';
353
                $attributeData['description'][] = Description::parse($rule)->getDescription();
354
                $attributeData['value'] = json_encode(['foo', 'bar', 'baz']);
355
                break;
356
            case 'mimetypes':
357 View Code Duplication
            case 'mimes':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
358
                $attributeData['description'][] = Description::parse($rule)->with($this->fancyImplode($parameters, ', ', ' or '))->getDescription();
359
                break;
360 View Code Duplication
            case 'required_if':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
361
                $attributeData['description'][] = Description::parse($rule)->with($this->splitValuePairs($parameters))->getDescription();
362
                break;
363 View Code Duplication
            case 'required_unless':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
364
                $attributeData['description'][] = Description::parse($rule)->with($this->splitValuePairs($parameters))->getDescription();
365
                break;
366 View Code Duplication
            case 'required_with':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
367
                $attributeData['description'][] = Description::parse($rule)->with($this->fancyImplode($parameters, ', ', ' or '))->getDescription();
368
                break;
369 View Code Duplication
            case 'required_with_all':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
370
                $attributeData['description'][] = Description::parse($rule)->with($this->fancyImplode($parameters, ', ', ' and '))->getDescription();
371
                break;
372 View Code Duplication
            case 'required_without':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
373
                $attributeData['description'][] = Description::parse($rule)->with($this->fancyImplode($parameters, ', ', ' or '))->getDescription();
374
                break;
375 View Code Duplication
            case 'required_without_all':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
376
                $attributeData['description'][] = Description::parse($rule)->with($this->fancyImplode($parameters, ', ', ' and '))->getDescription();
377
                break;
378
            case 'same':
379
                $attributeData['description'][] = Description::parse($rule)->with($parameters)->getDescription();
380
                break;
381
            case 'size':
382
                $attributeData['description'][] = Description::parse($rule)->with($parameters)->getDescription();
383
                break;
384 View Code Duplication
            case 'timezone':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
385
                $attributeData['description'][] = Description::parse($rule)->getDescription();
386
                $attributeData['value'] = $faker->timezone;
387
                break;
388
            case 'exists':
389
                $fieldName = isset($parameters[1]) ? $parameters[1] : $ruleName;
390
                $attributeData['description'][] = Description::parse($rule)->with([Str::singular($parameters[0]), $fieldName])->getDescription();
391
                break;
392
            case 'active_url':
393
                $attributeData['type'] = 'url';
394
                $attributeData['value'] = $faker->url;
395
                break;
396
            case 'regex':
397
                $attributeData['type'] = 'string';
398
                $attributeData['description'][] = Description::parse($rule)->with($parameters)->getDescription();
399
                break;
400
            case 'boolean':
401
                $attributeData['value'] = true;
402
                $attributeData['type'] = $rule;
403
                break;
404
            case 'array':
405
                $attributeData['value'] = $faker->word;
406
                $attributeData['type'] = $rule;
407
                break;
408
            case 'date':
409
                $attributeData['value'] = $faker->date();
410
                $attributeData['type'] = $rule;
411
                break;
412
            case 'email':
413
                $attributeData['value'] = $faker->safeEmail;
414
                $attributeData['type'] = $rule;
415
                break;
416
            case 'string':
417
                $attributeData['value'] = $faker->word;
418
                $attributeData['type'] = $rule;
419
                break;
420
            case 'integer':
421
                $attributeData['value'] = $faker->randomNumber();
422
                $attributeData['type'] = $rule;
423
                break;
424
            case 'numeric':
425
                $attributeData['value'] = $faker->randomNumber();
426
                $attributeData['type'] = $rule;
427
                break;
428
            case 'url':
429
                $attributeData['value'] = $faker->url;
430
                $attributeData['type'] = $rule;
431
                break;
432
            case 'ip':
433
                $attributeData['value'] = $faker->ipv4;
434
                $attributeData['type'] = $rule;
435
                break;
436
        }
437
438
        if ($attributeData['value'] === '') {
439
            $attributeData['value'] = $faker->word;
440
        }
441
442
        if (is_null($attributeData['type'])) {
443
            $attributeData['type'] = 'string';
444
        }
445
    }
446
447
    /**
448
     * Call the given URI and return the Response.
449
     *
450
     * @param  string  $method
451
     * @param  string  $uri
452
     * @param  array  $parameters
453
     * @param  array  $cookies
454
     * @param  array  $files
455
     * @param  array  $server
456
     * @param  string  $content
457
     *
458
     * @return \Illuminate\Http\Response
459
     */
460
    abstract public function callRoute($method, $uri, $parameters = [], $cookies = [], $files = [], $server = [], $content = null);
461
462
    /**
463
     * Transform headers array to array of $_SERVER vars with HTTP_* format.
464
     *
465
     * @param  array  $headers
466
     *
467
     * @return array
468
     */
469
    protected function transformHeadersToServerVars(array $headers)
470
    {
471
        $server = [];
472
        $prefix = 'HTTP_';
473
474
        foreach ($headers as $name => $value) {
475
            $name = strtr(strtoupper($name), '-', '_');
476
477
            if (! Str::startsWith($name, $prefix) && $name !== 'CONTENT_TYPE') {
478
                $name = $prefix.$name;
479
            }
480
481
            $server[$name] = $value;
482
        }
483
484
        return $server;
485
    }
486
487
    /**
488
     * Parse a string based rule.
489
     *
490
     * @param  string  $rules
491
     *
492
     * @return array
493
     */
494
    protected function parseStringRule($rules)
495
    {
496
        $parameters = [];
497
498
        // The format for specifying validation rules and parameters follows an
499
        // easy {rule}:{parameters} formatting convention. For instance the
500
        // rule "Max:3" states that the value may only be three letters.
501
        if (strpos($rules, ':') !== false) {
502
            list($rules, $parameter) = explode(':', $rules, 2);
503
504
            $parameters = $this->parseParameters($rules, $parameter);
505
        }
506
507
        return [strtolower(trim($rules)), $parameters];
508
    }
509
510
    /**
511
     * Parse a parameter list.
512
     *
513
     * @param  string  $rule
514
     * @param  string  $parameter
515
     *
516
     * @return array
517
     */
518
    protected function parseParameters($rule, $parameter)
519
    {
520
        if (strtolower($rule) === 'regex') {
521
            return [$parameter];
522
        }
523
524
        return str_getcsv($parameter);
525
    }
526
527
    /**
528
     * Normalizes a rule so that we can accept short types.
529
     *
530
     * @param  string $rule
531
     *
532
     * @return string
533
     */
534
    protected function normalizeRule($rule)
535
    {
536
        switch ($rule) {
537
            case 'int':
538
                return 'integer';
539
            case 'bool':
540
                return 'boolean';
541
            default:
542
                return $rule;
543
        }
544
    }
545
}
546