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

findPossibleMethod()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 9
rs 9.9666
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
3
namespace Facade\Ignition\SolutionProviders;
4
5
use Throwable;
6
use ReflectionClass;
7
use ReflectionMethod;
8
use BadMethodCallException;
9
use Illuminate\Support\Str;
10
use Illuminate\Support\Collection;
11
use Illuminate\Validation\Validator;
12
use Facade\IgnitionContracts\BaseSolution;
13
use Facade\IgnitionContracts\HasSolutionsForThrowable;
14
15
class UnknownValidationSolutionProvider implements HasSolutionsForThrowable
16
{
17
    protected const REGEX = '/Illuminate\\\\Validation\\\\Validator::(?P<method>validate(?!(Attribute|UsingCustomRule))[A-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
        return ! is_null($this->getMethodFromExceptionMessage($throwable->getMessage()));
26
    }
27
28
    public function getSolutions(Throwable $throwable): array
29
    {
30
        return [
31
            BaseSolution::create('Unknown Validation Rule')
32
                ->setSolutionDescription($this->getSolutionDescription($throwable)),
33
        ];
34
    }
35
36
    protected function getSolutionDescription(Throwable $throwable): string
37
    {
38
        $method = $this->getMethodFromExceptionMessage($throwable->getMessage());
39
40
        $possibleMethod = $this->findPossibleMethod($method);
41
        $rule = Str::snake(str_replace('validate', '', $possibleMethod));
42
43
        return "Did you mean `{$rule}` ?";
44
    }
45
46
    protected function getMethodFromExceptionMessage(string $message): ?string
47
    {
48
        if (! preg_match(self::REGEX, $message, $matches)) {
49
            return null;
50
        }
51
52
        return $matches['method'];
53
    }
54
55
    protected function findPossibleMethod(string $invalidMethodName)
56
    {
57
        return $this->getAvailableMethods()
58
            ->sortByDesc(function (string $method) use ($invalidMethodName) {
59
                similar_text($invalidMethodName, $method, $percentage);
60
61
                return $percentage;
62
            })->first();
63
    }
64
65
    protected function getAvailableMethods(): Collection
66
    {
67
        $class = new ReflectionClass(Validator::class);
68
69
        $extensions = Collection::make((\Illuminate\Support\Facades\Validator::make([], []))->extensions)
0 ignored issues
show
Bug introduced by
Accessing extensions on the interface Illuminate\Contracts\Validation\Validator suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
70
            ->keys()
71
            ->map(function (string $extension) {
72
                return 'validate'.Str::studly($extension);
73
            });
74
75
        return Collection::make($class->getMethods())
76
            ->filter(function (ReflectionMethod $method) {
77
                return preg_match('/(validate(?!(Attribute|UsingCustomRule))[A-Z][a-zA-Z]+)/', $method->name);
78
            })
79
            ->map(function (ReflectionMethod $method) {
80
                return $method->name;
81
            })
82
            ->merge($extensions);
83
    }
84
}
85