Subversion-Projekte lars-tiefland.laravel_shop

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php
2
 
3
namespace Spatie\Ignition\Solutions\SolutionProviders;
4
 
5
use BadMethodCallException;
6
use Illuminate\Support\Collection;
7
use ReflectionClass;
8
use ReflectionMethod;
9
use Spatie\Ignition\Contracts\BaseSolution;
10
use Spatie\Ignition\Contracts\HasSolutionsForThrowable;
11
use Throwable;
12
 
13
class BadMethodCallSolutionProvider implements HasSolutionsForThrowable
14
{
15
    protected const REGEX = '/([a-zA-Z\\\\]+)::([a-zA-Z]+)/m';
16
 
17
    public function canSolve(Throwable $throwable): bool
18
    {
19
        if (! $throwable instanceof BadMethodCallException) {
20
            return false;
21
        }
22
 
23
        if (is_null($this->getClassAndMethodFromExceptionMessage($throwable->getMessage()))) {
24
            return false;
25
        }
26
 
27
        return true;
28
    }
29
 
30
    public function getSolutions(Throwable $throwable): array
31
    {
32
        return [
33
            BaseSolution::create('Bad Method Call')
34
            ->setSolutionDescription($this->getSolutionDescription($throwable)),
35
        ];
36
    }
37
 
38
    public function getSolutionDescription(Throwable $throwable): string
39
    {
40
        if (! $this->canSolve($throwable)) {
41
            return '';
42
        }
43
 
44
        /** @phpstan-ignore-next-line  */
45
        extract($this->getClassAndMethodFromExceptionMessage($throwable->getMessage()), EXTR_OVERWRITE);
46
 
47
        $possibleMethod = $this->findPossibleMethod($class ?? '', $method ?? '');
48
 
49
        $class ??= 'UnknownClass';
50
 
51
        return "Did you mean {$class}::{$possibleMethod?->name}() ?";
52
    }
53
 
54
    /**
55
     * @param string $message
56
     *
57
     * @return null|array<string, mixed>
58
     */
59
    protected function getClassAndMethodFromExceptionMessage(string $message): ?array
60
    {
61
        if (! preg_match(self::REGEX, $message, $matches)) {
62
            return null;
63
        }
64
 
65
        return [
66
            'class' => $matches[1],
67
            'method' => $matches[2],
68
        ];
69
    }
70
 
71
    /**
72
     * @param class-string $class
73
     * @param string $invalidMethodName
74
     *
75
     * @return \ReflectionMethod|null
76
     */
77
    protected function findPossibleMethod(string $class, string $invalidMethodName): ?ReflectionMethod
78
    {
79
        return $this->getAvailableMethods($class)
80
            ->sortByDesc(function (ReflectionMethod $method) use ($invalidMethodName) {
81
                similar_text($invalidMethodName, $method->name, $percentage);
82
 
83
                return $percentage;
84
            })->first();
85
    }
86
 
87
    /**
88
     * @param class-string $class
89
     *
90
     * @return \Illuminate\Support\Collection<int, ReflectionMethod>
91
     */
92
    protected function getAvailableMethods(string $class): Collection
93
    {
94
        $class = new ReflectionClass($class);
95
 
96
        return Collection::make($class->getMethods());
97
    }
98
}