Upgrade framework
This commit is contained in:
98
vendor/spatie/ignition/src/Solutions/SolutionProviders/BadMethodCallSolutionProvider.php
vendored
Normal file
98
vendor/spatie/ignition/src/Solutions/SolutionProviders/BadMethodCallSolutionProvider.php
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\Ignition\Solutions\SolutionProviders;
|
||||
|
||||
use BadMethodCallException;
|
||||
use Illuminate\Support\Collection;
|
||||
use ReflectionClass;
|
||||
use ReflectionMethod;
|
||||
use Spatie\Ignition\Contracts\BaseSolution;
|
||||
use Spatie\Ignition\Contracts\HasSolutionsForThrowable;
|
||||
use Throwable;
|
||||
|
||||
class BadMethodCallSolutionProvider implements HasSolutionsForThrowable
|
||||
{
|
||||
protected const REGEX = '/([a-zA-Z\\\\]+)::([a-zA-Z]+)/m';
|
||||
|
||||
public function canSolve(Throwable $throwable): bool
|
||||
{
|
||||
if (! $throwable instanceof BadMethodCallException) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (is_null($this->getClassAndMethodFromExceptionMessage($throwable->getMessage()))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getSolutions(Throwable $throwable): array
|
||||
{
|
||||
return [
|
||||
BaseSolution::create('Bad Method Call')
|
||||
->setSolutionDescription($this->getSolutionDescription($throwable)),
|
||||
];
|
||||
}
|
||||
|
||||
public function getSolutionDescription(Throwable $throwable): string
|
||||
{
|
||||
if (! $this->canSolve($throwable)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
/** @phpstan-ignore-next-line */
|
||||
extract($this->getClassAndMethodFromExceptionMessage($throwable->getMessage()), EXTR_OVERWRITE);
|
||||
|
||||
$possibleMethod = $this->findPossibleMethod($class ?? '', $method ?? '');
|
||||
|
||||
$class ??= 'UnknownClass';
|
||||
|
||||
return "Did you mean {$class}::{$possibleMethod?->name}() ?";
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $message
|
||||
*
|
||||
* @return null|array<string, mixed>
|
||||
*/
|
||||
protected function getClassAndMethodFromExceptionMessage(string $message): ?array
|
||||
{
|
||||
if (! preg_match(self::REGEX, $message, $matches)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return [
|
||||
'class' => $matches[1],
|
||||
'method' => $matches[2],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param class-string $class
|
||||
* @param string $invalidMethodName
|
||||
*
|
||||
* @return \ReflectionMethod|null
|
||||
*/
|
||||
protected function findPossibleMethod(string $class, string $invalidMethodName): ?ReflectionMethod
|
||||
{
|
||||
return $this->getAvailableMethods($class)
|
||||
->sortByDesc(function (ReflectionMethod $method) use ($invalidMethodName) {
|
||||
similar_text($invalidMethodName, $method->name, $percentage);
|
||||
|
||||
return $percentage;
|
||||
})->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param class-string $class
|
||||
*
|
||||
* @return \Illuminate\Support\Collection<int, ReflectionMethod>
|
||||
*/
|
||||
protected function getAvailableMethods(string $class): Collection
|
||||
{
|
||||
$class = new ReflectionClass($class);
|
||||
|
||||
return Collection::make($class->getMethods());
|
||||
}
|
||||
}
|
||||
74
vendor/spatie/ignition/src/Solutions/SolutionProviders/MergeConflictSolutionProvider.php
vendored
Normal file
74
vendor/spatie/ignition/src/Solutions/SolutionProviders/MergeConflictSolutionProvider.php
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\Ignition\Solutions\SolutionProviders;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
use ParseError;
|
||||
use Spatie\Ignition\Contracts\BaseSolution;
|
||||
use Spatie\Ignition\Contracts\HasSolutionsForThrowable;
|
||||
use Throwable;
|
||||
|
||||
class MergeConflictSolutionProvider implements HasSolutionsForThrowable
|
||||
{
|
||||
public function canSolve(Throwable $throwable): bool
|
||||
{
|
||||
if (! ($throwable instanceof ParseError)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! $this->hasMergeConflictExceptionMessage($throwable)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$file = (string)file_get_contents($throwable->getFile());
|
||||
|
||||
if (! str_contains($file, '=======')) {
|
||||
return false;
|
||||
}
|
||||
if (! str_contains($file, '>>>>>>>')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getSolutions(Throwable $throwable): array
|
||||
{
|
||||
$file = (string)file_get_contents($throwable->getFile());
|
||||
preg_match('/\>\>\>\>\>\>\> (.*?)\n/', $file, $matches);
|
||||
$source = $matches[1];
|
||||
|
||||
$target = $this->getCurrentBranch(basename($throwable->getFile()));
|
||||
|
||||
return [
|
||||
BaseSolution::create("Merge conflict from branch '$source' into $target")
|
||||
->setSolutionDescription('You have a Git merge conflict. To undo your merge do `git reset --hard HEAD`'),
|
||||
];
|
||||
}
|
||||
|
||||
protected function getCurrentBranch(string $directory): string
|
||||
{
|
||||
$branch = "'".trim((string)shell_exec("cd {$directory}; git branch | grep \\* | cut -d ' ' -f2"))."'";
|
||||
|
||||
if ($branch === "''") {
|
||||
$branch = 'current branch';
|
||||
}
|
||||
|
||||
return $branch;
|
||||
}
|
||||
|
||||
protected function hasMergeConflictExceptionMessage(Throwable $throwable): bool
|
||||
{
|
||||
// For PHP 7.x and below
|
||||
if (Str::startsWith($throwable->getMessage(), 'syntax error, unexpected \'<<\'')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// For PHP 8+
|
||||
if (Str::startsWith($throwable->getMessage(), 'syntax error, unexpected token "<<"')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
101
vendor/spatie/ignition/src/Solutions/SolutionProviders/SolutionProviderRepository.php
vendored
Normal file
101
vendor/spatie/ignition/src/Solutions/SolutionProviders/SolutionProviderRepository.php
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\Ignition\Solutions\SolutionProviders;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
use Spatie\Ignition\Contracts\HasSolutionsForThrowable;
|
||||
use Spatie\Ignition\Contracts\ProvidesSolution;
|
||||
use Spatie\Ignition\Contracts\Solution;
|
||||
use Spatie\Ignition\Contracts\SolutionProviderRepository as SolutionProviderRepositoryContract;
|
||||
use Throwable;
|
||||
|
||||
class SolutionProviderRepository implements SolutionProviderRepositoryContract
|
||||
{
|
||||
/** @var Collection<int, class-string<HasSolutionsForThrowable>|HasSolutionsForThrowable> */
|
||||
protected Collection $solutionProviders;
|
||||
|
||||
/** @param array<int, class-string<HasSolutionsForThrowable>|HasSolutionsForThrowable> $solutionProviders */
|
||||
public function __construct(array $solutionProviders = [])
|
||||
{
|
||||
$this->solutionProviders = Collection::make($solutionProviders);
|
||||
}
|
||||
|
||||
public function registerSolutionProvider(string|HasSolutionsForThrowable $solutionProvider): SolutionProviderRepositoryContract
|
||||
{
|
||||
$this->solutionProviders->push($solutionProvider);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function registerSolutionProviders(array $solutionProviderClasses): SolutionProviderRepositoryContract
|
||||
{
|
||||
$this->solutionProviders = $this->solutionProviders->merge($solutionProviderClasses);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getSolutionsForThrowable(Throwable $throwable): array
|
||||
{
|
||||
$solutions = [];
|
||||
|
||||
if ($throwable instanceof Solution) {
|
||||
$solutions[] = $throwable;
|
||||
}
|
||||
|
||||
if ($throwable instanceof ProvidesSolution) {
|
||||
$solutions[] = $throwable->getSolution();
|
||||
}
|
||||
|
||||
$providedSolutions = $this
|
||||
->initialiseSolutionProviderRepositories()
|
||||
->filter(function (HasSolutionsForThrowable $solutionProvider) use ($throwable) {
|
||||
try {
|
||||
return $solutionProvider->canSolve($throwable);
|
||||
} catch (Throwable $exception) {
|
||||
return false;
|
||||
}
|
||||
})
|
||||
->map(function (HasSolutionsForThrowable $solutionProvider) use ($throwable) {
|
||||
try {
|
||||
return $solutionProvider->getSolutions($throwable);
|
||||
} catch (Throwable $exception) {
|
||||
return [];
|
||||
}
|
||||
})
|
||||
->flatten()
|
||||
->toArray();
|
||||
|
||||
return array_merge($solutions, $providedSolutions);
|
||||
}
|
||||
|
||||
public function getSolutionForClass(string $solutionClass): ?Solution
|
||||
{
|
||||
if (! class_exists($solutionClass)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (! in_array(Solution::class, class_implements($solutionClass) ?: [])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (! function_exists('app')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return app($solutionClass);
|
||||
}
|
||||
|
||||
/** @return Collection<int, HasSolutionsForThrowable> */
|
||||
protected function initialiseSolutionProviderRepositories(): Collection
|
||||
{
|
||||
return $this->solutionProviders
|
||||
->filter(fn (HasSolutionsForThrowable|string $provider) => in_array(HasSolutionsForThrowable::class, class_implements($provider) ?: []))
|
||||
->map(function (string|HasSolutionsForThrowable $provider): HasSolutionsForThrowable {
|
||||
if (is_string($provider)) {
|
||||
return new $provider;
|
||||
}
|
||||
|
||||
return $provider;
|
||||
});
|
||||
}
|
||||
}
|
||||
121
vendor/spatie/ignition/src/Solutions/SolutionProviders/UndefinedPropertySolutionProvider.php
vendored
Normal file
121
vendor/spatie/ignition/src/Solutions/SolutionProviders/UndefinedPropertySolutionProvider.php
vendored
Normal file
@@ -0,0 +1,121 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\Ignition\Solutions\SolutionProviders;
|
||||
|
||||
use ErrorException;
|
||||
use Illuminate\Support\Collection;
|
||||
use ReflectionClass;
|
||||
use ReflectionProperty;
|
||||
use Spatie\Ignition\Contracts\BaseSolution;
|
||||
use Spatie\Ignition\Contracts\HasSolutionsForThrowable;
|
||||
use Throwable;
|
||||
|
||||
class UndefinedPropertySolutionProvider implements HasSolutionsForThrowable
|
||||
{
|
||||
protected const REGEX = '/([a-zA-Z\\\\]+)::\$([a-zA-Z]+)/m';
|
||||
protected const MINIMUM_SIMILARITY = 80;
|
||||
|
||||
public function canSolve(Throwable $throwable): bool
|
||||
{
|
||||
if (! $throwable instanceof ErrorException) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (is_null($this->getClassAndPropertyFromExceptionMessage($throwable->getMessage()))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! $this->similarPropertyExists($throwable)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getSolutions(Throwable $throwable): array
|
||||
{
|
||||
return [
|
||||
BaseSolution::create('Unknown Property')
|
||||
->setSolutionDescription($this->getSolutionDescription($throwable)),
|
||||
];
|
||||
}
|
||||
|
||||
public function getSolutionDescription(Throwable $throwable): string
|
||||
{
|
||||
if (! $this->canSolve($throwable) || ! $this->similarPropertyExists($throwable)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
extract(
|
||||
/** @phpstan-ignore-next-line */
|
||||
$this->getClassAndPropertyFromExceptionMessage($throwable->getMessage()),
|
||||
EXTR_OVERWRITE,
|
||||
);
|
||||
|
||||
$possibleProperty = $this->findPossibleProperty($class ?? '', $property ?? '');
|
||||
|
||||
$class = $class ?? '';
|
||||
|
||||
return "Did you mean {$class}::\${$possibleProperty->name} ?";
|
||||
}
|
||||
|
||||
protected function similarPropertyExists(Throwable $throwable): bool
|
||||
{
|
||||
/** @phpstan-ignore-next-line */
|
||||
extract($this->getClassAndPropertyFromExceptionMessage($throwable->getMessage()), EXTR_OVERWRITE);
|
||||
|
||||
$possibleProperty = $this->findPossibleProperty($class ?? '', $property ?? '');
|
||||
|
||||
return $possibleProperty !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $message
|
||||
*
|
||||
* @return null|array<string, string>
|
||||
*/
|
||||
protected function getClassAndPropertyFromExceptionMessage(string $message): ?array
|
||||
{
|
||||
if (! preg_match(self::REGEX, $message, $matches)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return [
|
||||
'class' => $matches[1],
|
||||
'property' => $matches[2],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param class-string $class
|
||||
* @param string $invalidPropertyName
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
protected function findPossibleProperty(string $class, string $invalidPropertyName): mixed
|
||||
{
|
||||
return $this->getAvailableProperties($class)
|
||||
->sortByDesc(function (ReflectionProperty $property) use ($invalidPropertyName) {
|
||||
similar_text($invalidPropertyName, $property->name, $percentage);
|
||||
|
||||
return $percentage;
|
||||
})
|
||||
->filter(function (ReflectionProperty $property) use ($invalidPropertyName) {
|
||||
similar_text($invalidPropertyName, $property->name, $percentage);
|
||||
|
||||
return $percentage >= self::MINIMUM_SIMILARITY;
|
||||
})->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param class-string $class
|
||||
*
|
||||
* @return Collection<int, ReflectionProperty>
|
||||
*/
|
||||
protected function getAvailableProperties(string $class): Collection
|
||||
{
|
||||
$class = new ReflectionClass($class);
|
||||
|
||||
return Collection::make($class->getProperties());
|
||||
}
|
||||
}
|
||||
29
vendor/spatie/ignition/src/Solutions/SolutionTransformer.php
vendored
Normal file
29
vendor/spatie/ignition/src/Solutions/SolutionTransformer.php
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\Ignition\Solutions;
|
||||
|
||||
use Illuminate\Contracts\Support\Arrayable;
|
||||
use Spatie\Ignition\Contracts\Solution;
|
||||
|
||||
/** @implements Arrayable<string, array<string,string>|string|false> */
|
||||
class SolutionTransformer implements Arrayable
|
||||
{
|
||||
protected Solution $solution;
|
||||
|
||||
public function __construct(Solution $solution)
|
||||
{
|
||||
$this->solution = $solution;
|
||||
}
|
||||
|
||||
/** @return array<string, array<string,string>|string|false> */
|
||||
public function toArray(): array
|
||||
{
|
||||
return [
|
||||
'class' => get_class($this->solution),
|
||||
'title' => $this->solution->getSolutionTitle(),
|
||||
'links' => $this->solution->getDocumentationLinks(),
|
||||
'description' => $this->solution->getSolutionDescription(),
|
||||
'is_runnable' => false,
|
||||
];
|
||||
}
|
||||
}
|
||||
43
vendor/spatie/ignition/src/Solutions/SuggestCorrectVariableNameSolution.php
vendored
Normal file
43
vendor/spatie/ignition/src/Solutions/SuggestCorrectVariableNameSolution.php
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\Ignition\Solutions;
|
||||
|
||||
use Spatie\Ignition\Contracts\Solution;
|
||||
|
||||
class SuggestCorrectVariableNameSolution implements Solution
|
||||
{
|
||||
protected ?string $variableName;
|
||||
|
||||
protected ?string $viewFile;
|
||||
|
||||
protected ?string $suggested;
|
||||
|
||||
public function __construct(string $variableName = null, string $viewFile = null, string $suggested = null)
|
||||
{
|
||||
$this->variableName = $variableName;
|
||||
|
||||
$this->viewFile = $viewFile;
|
||||
|
||||
$this->suggested = $suggested;
|
||||
}
|
||||
|
||||
public function getSolutionTitle(): string
|
||||
{
|
||||
return 'Possible typo $'.$this->variableName;
|
||||
}
|
||||
|
||||
public function getDocumentationLinks(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
public function getSolutionDescription(): string
|
||||
{
|
||||
return "Did you mean `$$this->suggested`?";
|
||||
}
|
||||
|
||||
public function isRunnable(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
30
vendor/spatie/ignition/src/Solutions/SuggestImportSolution.php
vendored
Normal file
30
vendor/spatie/ignition/src/Solutions/SuggestImportSolution.php
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\Ignition\Solutions;
|
||||
|
||||
use Spatie\Ignition\Contracts\Solution;
|
||||
|
||||
class SuggestImportSolution implements Solution
|
||||
{
|
||||
protected string $class;
|
||||
|
||||
public function __construct(string $class)
|
||||
{
|
||||
$this->class = $class;
|
||||
}
|
||||
|
||||
public function getSolutionTitle(): string
|
||||
{
|
||||
return 'A class import is missing';
|
||||
}
|
||||
|
||||
public function getSolutionDescription(): string
|
||||
{
|
||||
return 'You have a missing class import. Try importing this class: `'.$this->class.'`.';
|
||||
}
|
||||
|
||||
public function getDocumentationLinks(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user