Completed
Pull Request — master (#125)
by
unknown
01:34
created

UnknownValidationSolutionProvider::getSolutions()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 7
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
3
namespace Facade\Ignition\SolutionProviders;
4
5
use BadMethodCallException;
6
use Facade\IgnitionContracts\BaseSolution;
7
use Facade\IgnitionContracts\HasSolutionsForThrowable;
8
use Illuminate\Support\Collection;
9
use Illuminate\Support\Str;
10
use Illuminate\Validation\Validator;
11
use ReflectionClass;
12
use ReflectionMethod;
13
use Throwable;
14
15
class UnknownValidationSolutionProvider implements HasSolutionsForThrowable
16
{
17
    protected const REGEX = '/([a-zA-Z\\\\]+)::([a-zA-Z]+)/m';
18
19
    public function canSolve(Throwable $throwable): bool
20
    {
21
        if (! $throwable instanceof BadMethodCallException) {
22
            return false;
23
        }
24
25
        if (is_null($this->getClassAndMethodFromExceptionMessage($throwable->getMessage()))) {
26
            return false;
27
        }
28
29
        extract($this->getClassAndMethodFromExceptionMessage($throwable->getMessage()), EXTR_OVERWRITE);
0 ignored issues
show
Bug introduced by
$this->getClassAndMethod...hrowable->getMessage()) cannot be passed to extract() as the parameter $var_array expects a reference.
Loading history...
30
31
        if ($class !== Validator::class || ! Str::startsWith($method, 'validate')) {
32
            return false;
33
        }
34
35
        return true;
36
    }
37
38
    public function getSolutions(Throwable $throwable): array
39
    {
40
        return [
41
            BaseSolution::create('Unknown Validation Rule')
42
                ->setSolutionDescription($this->getSolutionDescription($throwable)),
43
        ];
44
    }
45
46
    public function getSolutionDescription(Throwable $throwable): string
47
    {
48
        if (! $this->canSolve($throwable)) {
49
            return '';
50
        }
51
52
        extract($this->getClassAndMethodFromExceptionMessage($throwable->getMessage()), EXTR_OVERWRITE);
0 ignored issues
show
Bug introduced by
$this->getClassAndMethod...hrowable->getMessage()) cannot be passed to extract() as the parameter $var_array expects a reference.
Loading history...
53
54
        $possibleMethod = $this->findPossibleMethod($class, $method);
55
        $rule           = strtolower(str_replace('validate', '', $possibleMethod->name));
56
57
        return "Did you mean `{$rule}` ?";
58
    }
59
60
    protected function getClassAndMethodFromExceptionMessage(string $message): ?array
61
    {
62
        if (! preg_match(self::REGEX, $message, $matches)) {
63
            return null;
64
        }
65
66
        return [
67
            'class'  => $matches[1],
68
            'method' => $matches[2],
69
        ];
70
    }
71
72
    protected function findPossibleMethod(string $class, string $invalidMethodName)
73
    {
74
        return $this->getAvailableMethods($class)
75
            ->sortByDesc(function (ReflectionMethod $method) use ($invalidMethodName) {
76
                similar_text($invalidMethodName, $method->name, $percentage);
77
78
                return $percentage;
79
            })->first();
80
    }
81
82
    protected function getAvailableMethods($class): Collection
83
    {
84
        $class = new ReflectionClass($class);
85
86
        return Collection::make($class->getMethods())
87
            ->filter(function (ReflectionMethod $method) {
88
                return Str::startsWith($method->name, 'validate');
89
            });
90
    }
91
}
92