Primo Committ
This commit is contained in:
79
vendor/facade/ignition/src/SolutionProviders/BadMethodCallSolutionProvider.php
vendored
Normal file
79
vendor/facade/ignition/src/SolutionProviders/BadMethodCallSolutionProvider.php
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
namespace Facade\Ignition\SolutionProviders;
|
||||
|
||||
use BadMethodCallException;
|
||||
use Facade\IgnitionContracts\BaseSolution;
|
||||
use Facade\IgnitionContracts\HasSolutionsForThrowable;
|
||||
use Illuminate\Support\Collection;
|
||||
use ReflectionClass;
|
||||
use ReflectionMethod;
|
||||
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 '';
|
||||
}
|
||||
|
||||
extract($this->getClassAndMethodFromExceptionMessage($throwable->getMessage()), EXTR_OVERWRITE);
|
||||
|
||||
$possibleMethod = $this->findPossibleMethod($class, $method);
|
||||
|
||||
return "Did you mean {$class}::{$possibleMethod->name}() ?";
|
||||
}
|
||||
|
||||
protected function getClassAndMethodFromExceptionMessage(string $message): ?array
|
||||
{
|
||||
if (! preg_match(self::REGEX, $message, $matches)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return [
|
||||
'class' => $matches[1],
|
||||
'method' => $matches[2],
|
||||
];
|
||||
}
|
||||
|
||||
protected function findPossibleMethod(string $class, string $invalidMethodName)
|
||||
{
|
||||
return $this->getAvailableMethods($class)
|
||||
->sortByDesc(function (ReflectionMethod $method) use ($invalidMethodName) {
|
||||
similar_text($invalidMethodName, $method->name, $percentage);
|
||||
|
||||
return $percentage;
|
||||
})->first();
|
||||
}
|
||||
|
||||
protected function getAvailableMethods($class): Collection
|
||||
{
|
||||
$class = new ReflectionClass($class);
|
||||
|
||||
return Collection::make($class->getMethods());
|
||||
}
|
||||
}
|
||||
35
vendor/facade/ignition/src/SolutionProviders/DefaultDbNameSolutionProvider.php
vendored
Normal file
35
vendor/facade/ignition/src/SolutionProviders/DefaultDbNameSolutionProvider.php
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace Facade\Ignition\SolutionProviders;
|
||||
|
||||
use Facade\Ignition\Solutions\SuggestUsingCorrectDbNameSolution;
|
||||
use Facade\IgnitionContracts\HasSolutionsForThrowable;
|
||||
use Illuminate\Database\QueryException;
|
||||
use Throwable;
|
||||
|
||||
class DefaultDbNameSolutionProvider implements HasSolutionsForThrowable
|
||||
{
|
||||
public const MYSQL_UNKNOWN_DATABASE_CODE = 1049;
|
||||
|
||||
public function canSolve(Throwable $throwable): bool
|
||||
{
|
||||
if (! $throwable instanceof QueryException) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($throwable->getCode() !== self::MYSQL_UNKNOWN_DATABASE_CODE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! in_array(env('DB_DATABASE'), ['homestead', 'laravel'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getSolutions(Throwable $throwable): array
|
||||
{
|
||||
return [new SuggestUsingCorrectDbNameSolution()];
|
||||
}
|
||||
}
|
||||
67
vendor/facade/ignition/src/SolutionProviders/IncorrectValetDbCredentialsSolutionProvider.php
vendored
Normal file
67
vendor/facade/ignition/src/SolutionProviders/IncorrectValetDbCredentialsSolutionProvider.php
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
namespace Facade\Ignition\SolutionProviders;
|
||||
|
||||
use Facade\Ignition\Solutions\UseDefaultValetDbCredentialsSolution;
|
||||
use Facade\IgnitionContracts\HasSolutionsForThrowable;
|
||||
use Illuminate\Database\QueryException;
|
||||
use Throwable;
|
||||
|
||||
class IncorrectValetDbCredentialsSolutionProvider implements HasSolutionsForThrowable
|
||||
{
|
||||
public const MYSQL_ACCESS_DENIED_CODE = 1045;
|
||||
|
||||
public function canSolve(Throwable $throwable): bool
|
||||
{
|
||||
if (PHP_OS !== 'Darwin') {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! $throwable instanceof QueryException) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! $this->isAccessDeniedCode($throwable->getCode())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! $this->envFileExists()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! $this->isValetInstalled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($this->usingCorrectDefaultCredentials()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getSolutions(Throwable $throwable): array
|
||||
{
|
||||
return [new UseDefaultValetDbCredentialsSolution()];
|
||||
}
|
||||
|
||||
protected function envFileExists(): bool
|
||||
{
|
||||
return file_exists(base_path('.env'));
|
||||
}
|
||||
|
||||
protected function isAccessDeniedCode($code): bool
|
||||
{
|
||||
return $code === static::MYSQL_ACCESS_DENIED_CODE;
|
||||
}
|
||||
|
||||
protected function isValetInstalled(): bool
|
||||
{
|
||||
return file_exists('/usr/local/bin/valet');
|
||||
}
|
||||
|
||||
protected function usingCorrectDefaultCredentials(): bool
|
||||
{
|
||||
return env('DB_USERNAME') === 'root' && env('DB_PASSWORD') === '';
|
||||
}
|
||||
}
|
||||
79
vendor/facade/ignition/src/SolutionProviders/InvalidRouteActionSolutionProvider.php
vendored
Normal file
79
vendor/facade/ignition/src/SolutionProviders/InvalidRouteActionSolutionProvider.php
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
namespace Facade\Ignition\SolutionProviders;
|
||||
|
||||
use Facade\Ignition\Support\ComposerClassMap;
|
||||
use Facade\Ignition\Support\StringComparator;
|
||||
use Facade\IgnitionContracts\BaseSolution;
|
||||
use Facade\IgnitionContracts\HasSolutionsForThrowable;
|
||||
use Illuminate\Support\Str;
|
||||
use Throwable;
|
||||
use UnexpectedValueException;
|
||||
|
||||
class InvalidRouteActionSolutionProvider implements HasSolutionsForThrowable
|
||||
{
|
||||
protected const REGEX = '/\[([a-zA-Z\\\\]+)\]/m';
|
||||
|
||||
public function canSolve(Throwable $throwable): bool
|
||||
{
|
||||
if (! $throwable instanceof UnexpectedValueException) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! preg_match(self::REGEX, $throwable->getMessage(), $matches)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Str::startsWith($throwable->getMessage(), 'Invalid route action: ');
|
||||
}
|
||||
|
||||
public function getSolutions(Throwable $throwable): array
|
||||
{
|
||||
preg_match(self::REGEX, $throwable->getMessage(), $matches);
|
||||
|
||||
$invalidController = $matches[1] ?? null;
|
||||
|
||||
$suggestedController = $this->findRelatedController($invalidController);
|
||||
|
||||
if ($suggestedController === $invalidController) {
|
||||
return [
|
||||
BaseSolution::create("`{$invalidController}` is not invokable.")
|
||||
->setSolutionDescription("The controller class `{$invalidController}` is not invokable. Did you forget to add the `__invoke` method or is the controller's method missing in your routes file?"),
|
||||
];
|
||||
}
|
||||
|
||||
if ($suggestedController) {
|
||||
return [
|
||||
BaseSolution::create("`{$invalidController}` was not found.")
|
||||
->setSolutionDescription("Controller class `{$invalidController}` for one of your routes was not found. Did you mean `{$suggestedController}`?"),
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
BaseSolution::create("`{$invalidController}` was not found.")
|
||||
->setSolutionDescription("Controller class `{$invalidController}` for one of your routes was not found. Are you sure this controller exists and is imported correctly?"),
|
||||
];
|
||||
}
|
||||
|
||||
protected function findRelatedController(string $invalidController): ?string
|
||||
{
|
||||
$composerClassMap = app(ComposerClassMap::class);
|
||||
|
||||
$controllers = collect($composerClassMap->listClasses())
|
||||
->filter(function (string $_file, string $fqcn) {
|
||||
return Str::endsWith($fqcn, 'Controller');
|
||||
})
|
||||
->mapWithKeys(function (string $_file, string $fqcn) {
|
||||
return [$fqcn => class_basename($fqcn)];
|
||||
})
|
||||
->toArray();
|
||||
|
||||
$basenameMatch = StringComparator::findClosestMatch($controllers, $invalidController, 4);
|
||||
|
||||
$controllers = array_flip($controllers);
|
||||
|
||||
$fqcnMatch = StringComparator::findClosestMatch($controllers, $invalidController, 4);
|
||||
|
||||
return $fqcnMatch ?? $basenameMatch;
|
||||
}
|
||||
}
|
||||
41
vendor/facade/ignition/src/SolutionProviders/LazyLoadingViolationSolutionProvider.php
vendored
Normal file
41
vendor/facade/ignition/src/SolutionProviders/LazyLoadingViolationSolutionProvider.php
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace Facade\Ignition\SolutionProviders;
|
||||
|
||||
use Facade\Ignition\Support\LaravelVersion;
|
||||
use Facade\IgnitionContracts\BaseSolution;
|
||||
use Facade\IgnitionContracts\HasSolutionsForThrowable;
|
||||
use Illuminate\Database\LazyLoadingViolationException;
|
||||
use Throwable;
|
||||
|
||||
class LazyLoadingViolationSolutionProvider implements HasSolutionsForThrowable
|
||||
{
|
||||
public function canSolve(Throwable $throwable): bool
|
||||
{
|
||||
if ($throwable instanceof LazyLoadingViolationException) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (! $previous = $throwable->getPrevious()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $previous instanceof LazyLoadingViolationException;
|
||||
}
|
||||
|
||||
public function getSolutions(Throwable $throwable): array
|
||||
{
|
||||
$majorVersion = LaravelVersion::major();
|
||||
|
||||
return [BaseSolution::create(
|
||||
'Lazy loading was disabled to detect N+1 problems'
|
||||
)
|
||||
->setSolutionDescription(
|
||||
'Either avoid lazy loading the relation or allow lazy loading.'
|
||||
)
|
||||
->setDocumentationLinks([
|
||||
'Read the docs on preventing lazy loading' => "https://laravel.com/docs/{$majorVersion}.x/eloquent-relationships#preventing-lazy-loading",
|
||||
'Watch a video on how to deal with the N+1 problem' => 'https://www.youtube.com/watch?v=ZE7KBeraVpc',
|
||||
]),];
|
||||
}
|
||||
}
|
||||
75
vendor/facade/ignition/src/SolutionProviders/MergeConflictSolutionProvider.php
vendored
Normal file
75
vendor/facade/ignition/src/SolutionProviders/MergeConflictSolutionProvider.php
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
namespace Facade\Ignition\SolutionProviders;
|
||||
|
||||
use Facade\IgnitionContracts\BaseSolution;
|
||||
use Facade\IgnitionContracts\HasSolutionsForThrowable;
|
||||
use Illuminate\Support\Str;
|
||||
use ParseError;
|
||||
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 = file_get_contents($throwable->getFile());
|
||||
|
||||
if (strpos($file, '=======') === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (strpos($file, '>>>>>>>') === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getSolutions(Throwable $throwable): array
|
||||
{
|
||||
$file = 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(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;
|
||||
}
|
||||
}
|
||||
25
vendor/facade/ignition/src/SolutionProviders/MissingAppKeySolutionProvider.php
vendored
Normal file
25
vendor/facade/ignition/src/SolutionProviders/MissingAppKeySolutionProvider.php
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Facade\Ignition\SolutionProviders;
|
||||
|
||||
use Facade\Ignition\Solutions\GenerateAppKeySolution;
|
||||
use Facade\IgnitionContracts\HasSolutionsForThrowable;
|
||||
use RuntimeException;
|
||||
use Throwable;
|
||||
|
||||
class MissingAppKeySolutionProvider implements HasSolutionsForThrowable
|
||||
{
|
||||
public function canSolve(Throwable $throwable): bool
|
||||
{
|
||||
if (! $throwable instanceof RuntimeException) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $throwable->getMessage() === 'No application encryption key has been specified.';
|
||||
}
|
||||
|
||||
public function getSolutions(Throwable $throwable): array
|
||||
{
|
||||
return [new GenerateAppKeySolution()];
|
||||
}
|
||||
}
|
||||
35
vendor/facade/ignition/src/SolutionProviders/MissingColumnSolutionProvider.php
vendored
Normal file
35
vendor/facade/ignition/src/SolutionProviders/MissingColumnSolutionProvider.php
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace Facade\Ignition\SolutionProviders;
|
||||
|
||||
use Facade\Ignition\Solutions\RunMigrationsSolution;
|
||||
use Facade\IgnitionContracts\HasSolutionsForThrowable;
|
||||
use Illuminate\Database\QueryException;
|
||||
use Throwable;
|
||||
|
||||
class MissingColumnSolutionProvider implements HasSolutionsForThrowable
|
||||
{
|
||||
/**
|
||||
* See https://dev.mysql.com/doc/refman/8.0/en/server-error-reference.html#error_er_bad_field_error.
|
||||
*/
|
||||
public const MYSQL_BAD_FIELD_CODE = '42S22';
|
||||
|
||||
public function canSolve(Throwable $throwable): bool
|
||||
{
|
||||
if (! $throwable instanceof QueryException) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->isBadTableErrorCode($throwable->getCode());
|
||||
}
|
||||
|
||||
protected function isBadTableErrorCode($code): bool
|
||||
{
|
||||
return $code === static::MYSQL_BAD_FIELD_CODE;
|
||||
}
|
||||
|
||||
public function getSolutions(Throwable $throwable): array
|
||||
{
|
||||
return [new RunMigrationsSolution('A column was not found')];
|
||||
}
|
||||
}
|
||||
48
vendor/facade/ignition/src/SolutionProviders/MissingImportSolutionProvider.php
vendored
Normal file
48
vendor/facade/ignition/src/SolutionProviders/MissingImportSolutionProvider.php
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace Facade\Ignition\SolutionProviders;
|
||||
|
||||
use Facade\Ignition\Solutions\SuggestImportSolution;
|
||||
use Facade\Ignition\Support\ComposerClassMap;
|
||||
use Facade\IgnitionContracts\HasSolutionsForThrowable;
|
||||
use Throwable;
|
||||
|
||||
class MissingImportSolutionProvider implements HasSolutionsForThrowable
|
||||
{
|
||||
/** @var string */
|
||||
protected $foundClass;
|
||||
|
||||
/** @var \Facade\Ignition\Support\ComposerClassMap */
|
||||
protected $composerClassMap;
|
||||
|
||||
public function canSolve(Throwable $throwable): bool
|
||||
{
|
||||
$pattern = '/Class \'([^\s]+)\' not found/m';
|
||||
|
||||
if (! preg_match($pattern, $throwable->getMessage(), $matches)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$class = $matches[1];
|
||||
|
||||
$this->composerClassMap = new ComposerClassMap();
|
||||
|
||||
$this->search($class);
|
||||
|
||||
return ! is_null($this->foundClass);
|
||||
}
|
||||
|
||||
public function getSolutions(Throwable $throwable): array
|
||||
{
|
||||
return [new SuggestImportSolution($this->foundClass)];
|
||||
}
|
||||
|
||||
protected function search(string $missingClass)
|
||||
{
|
||||
$this->foundClass = $this->composerClassMap->searchClassMap($missingClass);
|
||||
|
||||
if (is_null($this->foundClass)) {
|
||||
$this->foundClass = $this->composerClassMap->searchPsrMaps($missingClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
42
vendor/facade/ignition/src/SolutionProviders/MissingLivewireComponentSolutionProvider.php
vendored
Normal file
42
vendor/facade/ignition/src/SolutionProviders/MissingLivewireComponentSolutionProvider.php
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace Facade\Ignition\SolutionProviders;
|
||||
|
||||
use Facade\Ignition\Solutions\LivewireDiscoverSolution;
|
||||
use Facade\IgnitionContracts\HasSolutionsForThrowable;
|
||||
use Livewire\Exceptions\ComponentNotFoundException;
|
||||
use Livewire\LivewireComponentsFinder;
|
||||
use Throwable;
|
||||
|
||||
class MissingLivewireComponentSolutionProvider implements HasSolutionsForThrowable
|
||||
{
|
||||
public function canSolve(Throwable $throwable): bool
|
||||
{
|
||||
if (! $this->livewireIsInstalled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! $throwable instanceof ComponentNotFoundException) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getSolutions(Throwable $throwable): array
|
||||
{
|
||||
return [new LivewireDiscoverSolution('A Livewire component was not found')];
|
||||
}
|
||||
|
||||
public function livewireIsInstalled(): bool
|
||||
{
|
||||
if (! class_exists(ComponentNotFoundException::class)) {
|
||||
return false;
|
||||
}
|
||||
if (! class_exists(LivewireComponentsFinder::class)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
24
vendor/facade/ignition/src/SolutionProviders/MissingMixManifestSolutionProvider.php
vendored
Normal file
24
vendor/facade/ignition/src/SolutionProviders/MissingMixManifestSolutionProvider.php
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Facade\Ignition\SolutionProviders;
|
||||
|
||||
use Facade\IgnitionContracts\BaseSolution;
|
||||
use Facade\IgnitionContracts\HasSolutionsForThrowable;
|
||||
use Illuminate\Support\Str;
|
||||
use Throwable;
|
||||
|
||||
class MissingMixManifestSolutionProvider implements HasSolutionsForThrowable
|
||||
{
|
||||
public function canSolve(Throwable $throwable): bool
|
||||
{
|
||||
return Str::startsWith($throwable->getMessage(), 'The Mix manifest does not exist');
|
||||
}
|
||||
|
||||
public function getSolutions(Throwable $throwable): array
|
||||
{
|
||||
return [
|
||||
BaseSolution::create('Missing Mix Manifest File')
|
||||
->setSolutionDescription('Did you forget to run `npm ci && npm run dev`?'),
|
||||
];
|
||||
}
|
||||
}
|
||||
58
vendor/facade/ignition/src/SolutionProviders/MissingPackageSolutionProvider.php
vendored
Normal file
58
vendor/facade/ignition/src/SolutionProviders/MissingPackageSolutionProvider.php
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace Facade\Ignition\SolutionProviders;
|
||||
|
||||
use Facade\Ignition\Solutions\MissingPackageSolution;
|
||||
use Facade\Ignition\Support\Packagist\Package;
|
||||
use Facade\Ignition\Support\Packagist\Packagist;
|
||||
use Facade\IgnitionContracts\HasSolutionsForThrowable;
|
||||
use Illuminate\Support\Str;
|
||||
use Throwable;
|
||||
|
||||
class MissingPackageSolutionProvider implements HasSolutionsForThrowable
|
||||
{
|
||||
/** @var \Facade\Ignition\Support\Packagist\Package|null */
|
||||
protected $package;
|
||||
|
||||
public function canSolve(Throwable $throwable): bool
|
||||
{
|
||||
$pattern = '/Class \'([^\s]+)\' not found/m';
|
||||
|
||||
if (! preg_match($pattern, $throwable->getMessage(), $matches)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$class = $matches[1];
|
||||
|
||||
if (Str::startsWith($class, app()->getNamespace())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->package = $this->findPackageFromClassName($class);
|
||||
|
||||
return ! is_null($this->package);
|
||||
}
|
||||
|
||||
public function getSolutions(Throwable $throwable): array
|
||||
{
|
||||
return [new MissingPackageSolution($this->package)];
|
||||
}
|
||||
|
||||
protected function findPackageFromClassName(string $missingClassName): ?Package
|
||||
{
|
||||
if (! $package = $this->findComposerPackageForClassName($missingClassName)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $package->hasNamespaceThatContainsClassName($missingClassName)
|
||||
? $package
|
||||
: null;
|
||||
}
|
||||
|
||||
protected function findComposerPackageForClassName(string $className): ?Package
|
||||
{
|
||||
$packages = Packagist::findPackagesForClassName($className);
|
||||
|
||||
return $packages[0] ?? null;
|
||||
}
|
||||
}
|
||||
63
vendor/facade/ignition/src/SolutionProviders/RouteNotDefinedSolutionProvider.php
vendored
Normal file
63
vendor/facade/ignition/src/SolutionProviders/RouteNotDefinedSolutionProvider.php
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace Facade\Ignition\SolutionProviders;
|
||||
|
||||
use Facade\Ignition\Exceptions\ViewException;
|
||||
use Facade\Ignition\Support\StringComparator;
|
||||
use Facade\IgnitionContracts\BaseSolution;
|
||||
use Facade\IgnitionContracts\HasSolutionsForThrowable;
|
||||
use Illuminate\Foundation\Application;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use InvalidArgumentException;
|
||||
use Symfony\Component\Routing\Exception\RouteNotFoundException;
|
||||
use Throwable;
|
||||
|
||||
class RouteNotDefinedSolutionProvider implements HasSolutionsForThrowable
|
||||
{
|
||||
protected const REGEX = '/Route \[(.*)\] not defined/m';
|
||||
|
||||
public function canSolve(Throwable $throwable): bool
|
||||
{
|
||||
if (version_compare(Application::VERSION, '6.0.0', '>=')) {
|
||||
if (! $throwable instanceof RouteNotFoundException) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (version_compare(Application::VERSION, '6.0.0', '<')) {
|
||||
if (! $throwable instanceof InvalidArgumentException && ! $throwable instanceof ViewException) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return (bool)preg_match(self::REGEX, $throwable->getMessage(), $matches);
|
||||
}
|
||||
|
||||
public function getSolutions(Throwable $throwable): array
|
||||
{
|
||||
preg_match(self::REGEX, $throwable->getMessage(), $matches);
|
||||
|
||||
$missingRoute = $matches[1] ?? null;
|
||||
|
||||
$suggestedRoute = $this->findRelatedRoute($missingRoute);
|
||||
|
||||
if ($suggestedRoute) {
|
||||
return [
|
||||
BaseSolution::create("{$missingRoute} was not defined.")
|
||||
->setSolutionDescription("Did you mean `{$suggestedRoute}`?"),
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
BaseSolution::create("{$missingRoute} was not defined.")
|
||||
->setSolutionDescription('Are you sure that the route is defined'),
|
||||
];
|
||||
}
|
||||
|
||||
protected function findRelatedRoute(string $missingRoute): ?string
|
||||
{
|
||||
Route::getRoutes()->refreshNameLookups();
|
||||
|
||||
return StringComparator::findClosestMatch(array_keys(Route::getRoutes()->getRoutesByName()), $missingRoute);
|
||||
}
|
||||
}
|
||||
30
vendor/facade/ignition/src/SolutionProviders/RunningLaravelDuskInProductionProvider.php
vendored
Normal file
30
vendor/facade/ignition/src/SolutionProviders/RunningLaravelDuskInProductionProvider.php
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace Facade\Ignition\SolutionProviders;
|
||||
|
||||
use Exception;
|
||||
use Facade\IgnitionContracts\BaseSolution;
|
||||
use Facade\IgnitionContracts\HasSolutionsForThrowable;
|
||||
use Throwable;
|
||||
|
||||
class RunningLaravelDuskInProductionProvider implements HasSolutionsForThrowable
|
||||
{
|
||||
public function canSolve(Throwable $throwable): bool
|
||||
{
|
||||
if (! $throwable instanceof Exception) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $throwable->getMessage() === 'It is unsafe to run Dusk in production.';
|
||||
}
|
||||
|
||||
public function getSolutions(Throwable $throwable): array
|
||||
{
|
||||
return [
|
||||
BaseSolution::create('Laravel Dusk should not be run in production.')
|
||||
->setSolutionDescription('Install the dependencies with the `--no-dev` flag.'),
|
||||
BaseSolution::create('Laravel Dusk can be run in other environments.')
|
||||
->setSolutionDescription('Consider setting the `APP_ENV` to something other than `production` like `local` for example.'),
|
||||
];
|
||||
}
|
||||
}
|
||||
95
vendor/facade/ignition/src/SolutionProviders/SolutionProviderRepository.php
vendored
Normal file
95
vendor/facade/ignition/src/SolutionProviders/SolutionProviderRepository.php
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
|
||||
namespace Facade\Ignition\SolutionProviders;
|
||||
|
||||
use Facade\IgnitionContracts\HasSolutionsForThrowable;
|
||||
use Facade\IgnitionContracts\ProvidesSolution;
|
||||
use Facade\IgnitionContracts\Solution;
|
||||
use Facade\IgnitionContracts\SolutionProviderRepository as SolutionProviderRepositoryContract;
|
||||
use Illuminate\Support\Collection;
|
||||
use Throwable;
|
||||
|
||||
class SolutionProviderRepository implements SolutionProviderRepositoryContract
|
||||
{
|
||||
/** @var \Illuminate\Support\Collection */
|
||||
protected $solutionProviders;
|
||||
|
||||
public function __construct(array $solutionProviders = [])
|
||||
{
|
||||
$this->solutionProviders = Collection::make($solutionProviders);
|
||||
}
|
||||
|
||||
public function registerSolutionProvider(string $solutionProviderClass): SolutionProviderRepositoryContract
|
||||
{
|
||||
$this->solutionProviders->push($solutionProviderClass);
|
||||
|
||||
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->solutionProviders
|
||||
->filter(function (string $solutionClass) {
|
||||
if (! in_array(HasSolutionsForThrowable::class, class_implements($solutionClass))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (in_array($solutionClass, config('ignition.ignored_solution_providers', []))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
})
|
||||
->map(function (string $solutionClass) {
|
||||
return app($solutionClass);
|
||||
})
|
||||
->filter(function (HasSolutionsForThrowable $solutionProvider) use ($throwable) {
|
||||
try {
|
||||
return $solutionProvider->canSolve($throwable);
|
||||
} catch (Throwable $e) {
|
||||
return false;
|
||||
}
|
||||
})
|
||||
->map(function (HasSolutionsForThrowable $solutionProvider) use ($throwable) {
|
||||
try {
|
||||
return $solutionProvider->getSolutions($throwable);
|
||||
} catch (Throwable $e) {
|
||||
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;
|
||||
}
|
||||
|
||||
return app($solutionClass);
|
||||
}
|
||||
}
|
||||
35
vendor/facade/ignition/src/SolutionProviders/TableNotFoundSolutionProvider.php
vendored
Normal file
35
vendor/facade/ignition/src/SolutionProviders/TableNotFoundSolutionProvider.php
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace Facade\Ignition\SolutionProviders;
|
||||
|
||||
use Facade\Ignition\Solutions\RunMigrationsSolution;
|
||||
use Facade\IgnitionContracts\HasSolutionsForThrowable;
|
||||
use Illuminate\Database\QueryException;
|
||||
use Throwable;
|
||||
|
||||
class TableNotFoundSolutionProvider implements HasSolutionsForThrowable
|
||||
{
|
||||
/**
|
||||
* See https://dev.mysql.com/doc/refman/8.0/en/server-error-reference.html#error_er_bad_table_error.
|
||||
*/
|
||||
public const MYSQL_BAD_TABLE_CODE = '42S02';
|
||||
|
||||
public function canSolve(Throwable $throwable): bool
|
||||
{
|
||||
if (! $throwable instanceof QueryException) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->isBadTableErrorCode($throwable->getCode());
|
||||
}
|
||||
|
||||
protected function isBadTableErrorCode($code): bool
|
||||
{
|
||||
return $code === static::MYSQL_BAD_TABLE_CODE;
|
||||
}
|
||||
|
||||
public function getSolutions(Throwable $throwable): array
|
||||
{
|
||||
return [new RunMigrationsSolution('A table was not found')];
|
||||
}
|
||||
}
|
||||
48
vendor/facade/ignition/src/SolutionProviders/UndefinedLivewireMethodSolutionProvider.php
vendored
Normal file
48
vendor/facade/ignition/src/SolutionProviders/UndefinedLivewireMethodSolutionProvider.php
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace Facade\Ignition\SolutionProviders;
|
||||
|
||||
use Facade\Ignition\Solutions\SuggestLivewireMethodNameSolution;
|
||||
use Facade\Ignition\Support\LivewireComponentParser;
|
||||
use Facade\IgnitionContracts\HasSolutionsForThrowable;
|
||||
use Livewire\Exceptions\MethodNotFoundException;
|
||||
use Throwable;
|
||||
|
||||
class UndefinedLivewireMethodSolutionProvider implements HasSolutionsForThrowable
|
||||
{
|
||||
public function canSolve(Throwable $throwable): bool
|
||||
{
|
||||
return $throwable instanceof MethodNotFoundException;
|
||||
}
|
||||
|
||||
public function getSolutions(Throwable $throwable): array
|
||||
{
|
||||
['methodName' => $methodName, 'component' => $component] = $this->getMethodAndComponent($throwable);
|
||||
|
||||
if ($methodName === null || $component === null) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$parsed = LivewireComponentParser::create($component);
|
||||
|
||||
return $parsed->getMethodNamesLike($methodName)
|
||||
->map(function (string $suggested) use ($parsed, $methodName) {
|
||||
return new SuggestLivewireMethodNameSolution(
|
||||
$methodName,
|
||||
$parsed->getComponentClass(),
|
||||
$suggested
|
||||
);
|
||||
})
|
||||
->toArray();
|
||||
}
|
||||
|
||||
protected function getMethodAndComponent(Throwable $throwable): array
|
||||
{
|
||||
preg_match_all('/\[([\d\w\-_]*)\]/m', $throwable->getMessage(), $matches, PREG_SET_ORDER);
|
||||
|
||||
return [
|
||||
'methodName' => $matches[0][1] ?? null,
|
||||
'component' => $matches[1][1] ?? null,
|
||||
];
|
||||
}
|
||||
}
|
||||
49
vendor/facade/ignition/src/SolutionProviders/UndefinedLivewirePropertySolutionProvider.php
vendored
Normal file
49
vendor/facade/ignition/src/SolutionProviders/UndefinedLivewirePropertySolutionProvider.php
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace Facade\Ignition\SolutionProviders;
|
||||
|
||||
use Facade\Ignition\Solutions\SuggestLivewirePropertyNameSolution;
|
||||
use Facade\Ignition\Support\LivewireComponentParser;
|
||||
use Facade\IgnitionContracts\HasSolutionsForThrowable;
|
||||
use Livewire\Exceptions\PropertyNotFoundException;
|
||||
use Livewire\Exceptions\PublicPropertyNotFoundException;
|
||||
use Throwable;
|
||||
|
||||
class UndefinedLivewirePropertySolutionProvider implements HasSolutionsForThrowable
|
||||
{
|
||||
public function canSolve(Throwable $throwable): bool
|
||||
{
|
||||
return $throwable instanceof PropertyNotFoundException || $throwable instanceof PublicPropertyNotFoundException;
|
||||
}
|
||||
|
||||
public function getSolutions(Throwable $throwable): array
|
||||
{
|
||||
['variable' => $variable, 'component' => $component] = $this->getMethodAndComponent($throwable);
|
||||
|
||||
if ($variable === null || $component === null) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$parsed = LivewireComponentParser::create($component);
|
||||
|
||||
return $parsed->getPropertyNamesLike($variable)
|
||||
->map(function (string $suggested) use ($parsed, $variable) {
|
||||
return new SuggestLivewirePropertyNameSolution(
|
||||
$variable,
|
||||
$parsed->getComponentClass(),
|
||||
'$'.$suggested
|
||||
);
|
||||
})
|
||||
->toArray();
|
||||
}
|
||||
|
||||
protected function getMethodAndComponent(Throwable $throwable): array
|
||||
{
|
||||
preg_match_all('/\[([\d\w\-_\$]*)\]/m', $throwable->getMessage(), $matches, PREG_SET_ORDER, 0);
|
||||
|
||||
return [
|
||||
'variable' => $matches[0][1] ?? null,
|
||||
'component' => $matches[1][1] ?? null,
|
||||
];
|
||||
}
|
||||
}
|
||||
98
vendor/facade/ignition/src/SolutionProviders/UndefinedPropertySolutionProvider.php
vendored
Normal file
98
vendor/facade/ignition/src/SolutionProviders/UndefinedPropertySolutionProvider.php
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
namespace Facade\Ignition\SolutionProviders;
|
||||
|
||||
use ErrorException;
|
||||
use Facade\IgnitionContracts\BaseSolution;
|
||||
use Facade\IgnitionContracts\HasSolutionsForThrowable;
|
||||
use Illuminate\Support\Collection;
|
||||
use ReflectionClass;
|
||||
use ReflectionProperty;
|
||||
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($this->getClassAndPropertyFromExceptionMessage($throwable->getMessage()), EXTR_OVERWRITE);
|
||||
|
||||
$possibleProperty = $this->findPossibleProperty($class, $property);
|
||||
|
||||
return "Did you mean {$class}::\${$possibleProperty->name} ?";
|
||||
}
|
||||
|
||||
protected function similarPropertyExists(Throwable $throwable)
|
||||
{
|
||||
extract($this->getClassAndPropertyFromExceptionMessage($throwable->getMessage()), EXTR_OVERWRITE);
|
||||
|
||||
$possibleProperty = $this->findPossibleProperty($class, $property);
|
||||
|
||||
return $possibleProperty !== null;
|
||||
}
|
||||
|
||||
protected function getClassAndPropertyFromExceptionMessage(string $message): ?array
|
||||
{
|
||||
if (! preg_match(self::REGEX, $message, $matches)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return [
|
||||
'class' => $matches[1],
|
||||
'property' => $matches[2],
|
||||
];
|
||||
}
|
||||
|
||||
protected function findPossibleProperty(string $class, string $invalidPropertyName)
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
protected function getAvailableProperties($class): Collection
|
||||
{
|
||||
$class = new ReflectionClass($class);
|
||||
|
||||
return Collection::make($class->getProperties());
|
||||
}
|
||||
}
|
||||
95
vendor/facade/ignition/src/SolutionProviders/UndefinedVariableSolutionProvider.php
vendored
Normal file
95
vendor/facade/ignition/src/SolutionProviders/UndefinedVariableSolutionProvider.php
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
|
||||
namespace Facade\Ignition\SolutionProviders;
|
||||
|
||||
use Facade\Ignition\Exceptions\ViewException;
|
||||
use Facade\Ignition\Solutions\MakeViewVariableOptionalSolution;
|
||||
use Facade\Ignition\Solutions\SuggestCorrectVariableNameSolution;
|
||||
use Facade\IgnitionContracts\BaseSolution;
|
||||
use Facade\IgnitionContracts\HasSolutionsForThrowable;
|
||||
use Throwable;
|
||||
|
||||
class UndefinedVariableSolutionProvider implements HasSolutionsForThrowable
|
||||
{
|
||||
private $variableName;
|
||||
|
||||
private $viewFile;
|
||||
|
||||
public function canSolve(Throwable $throwable): bool
|
||||
{
|
||||
if (! $throwable instanceof ViewException) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->getNameAndView($throwable) !== null;
|
||||
}
|
||||
|
||||
public function getSolutions(Throwable $throwable): array
|
||||
{
|
||||
$solutions = [];
|
||||
|
||||
extract($this->getNameAndView($throwable));
|
||||
|
||||
if (! isset($variableName)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$solutions = $this->findCorrectVariableSolutions($throwable, $variableName, $viewFile);
|
||||
$solutions[] = $this->findOptionalVariableSolution($variableName, $viewFile);
|
||||
|
||||
return $solutions;
|
||||
}
|
||||
|
||||
protected function findCorrectVariableSolutions(
|
||||
ViewException $throwable,
|
||||
string $variableName,
|
||||
string $viewFile
|
||||
): array {
|
||||
return collect($throwable->getViewData())
|
||||
->map(function ($value, $key) use ($variableName) {
|
||||
similar_text($variableName, $key, $percentage);
|
||||
|
||||
return ['match' => $percentage, 'value' => $value];
|
||||
})
|
||||
->sortByDesc('match')->filter(function ($var) {
|
||||
return $var['match'] > 40;
|
||||
})
|
||||
->keys()
|
||||
->map(function ($suggestion) use ($variableName, $viewFile) {
|
||||
return new SuggestCorrectVariableNameSolution($variableName, $viewFile, $suggestion);
|
||||
})
|
||||
->map(function ($solution) {
|
||||
return $solution->isRunnable()
|
||||
? $solution
|
||||
: BaseSolution::create($solution->getSolutionTitle())
|
||||
->setSolutionDescription($solution->getSolutionDescription());
|
||||
})
|
||||
->toArray();
|
||||
}
|
||||
|
||||
protected function findOptionalVariableSolution(string $variableName, string $viewFile)
|
||||
{
|
||||
$optionalSolution = new MakeViewVariableOptionalSolution($variableName, $viewFile);
|
||||
|
||||
return $optionalSolution->isRunnable()
|
||||
? $optionalSolution
|
||||
: BaseSolution::create($optionalSolution->getSolutionTitle())
|
||||
->setSolutionDescription($optionalSolution->getSolutionDescription());
|
||||
}
|
||||
|
||||
protected function getNameAndView(Throwable $throwable): ?array
|
||||
{
|
||||
$pattern = '/Undefined variable:? (.*?) \(View: (.*?)\)/';
|
||||
|
||||
preg_match($pattern, $throwable->getMessage(), $matches);
|
||||
|
||||
if (count($matches) === 3) {
|
||||
[, $variableName, $viewFile] = $matches;
|
||||
$variableName = ltrim($variableName, '$');
|
||||
|
||||
return compact('variableName', 'viewFile');
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
83
vendor/facade/ignition/src/SolutionProviders/UnknownValidationSolutionProvider.php
vendored
Normal file
83
vendor/facade/ignition/src/SolutionProviders/UnknownValidationSolutionProvider.php
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
namespace Facade\Ignition\SolutionProviders;
|
||||
|
||||
use BadMethodCallException;
|
||||
use Facade\Ignition\Support\StringComparator;
|
||||
use Facade\IgnitionContracts\BaseSolution;
|
||||
use Facade\IgnitionContracts\HasSolutionsForThrowable;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Validation\Validator;
|
||||
use ReflectionClass;
|
||||
use ReflectionMethod;
|
||||
use Throwable;
|
||||
|
||||
class UnknownValidationSolutionProvider implements HasSolutionsForThrowable
|
||||
{
|
||||
protected const REGEX = '/Illuminate\\\\Validation\\\\Validator::(?P<method>validate(?!(Attribute|UsingCustomRule))[A-Z][a-zA-Z]+)/m';
|
||||
|
||||
public function canSolve(Throwable $throwable): bool
|
||||
{
|
||||
if (! $throwable instanceof BadMethodCallException) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ! is_null($this->getMethodFromExceptionMessage($throwable->getMessage()));
|
||||
}
|
||||
|
||||
public function getSolutions(Throwable $throwable): array
|
||||
{
|
||||
return [
|
||||
BaseSolution::create('Unknown Validation Rule')
|
||||
->setSolutionDescription($this->getSolutionDescription($throwable)),
|
||||
];
|
||||
}
|
||||
|
||||
protected function getSolutionDescription(Throwable $throwable): string
|
||||
{
|
||||
$method = $this->getMethodFromExceptionMessage($throwable->getMessage());
|
||||
|
||||
$possibleMethod = StringComparator::findSimilarText(
|
||||
$this->getAvailableMethods()->toArray(),
|
||||
$method
|
||||
);
|
||||
|
||||
if (empty($possibleMethod)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$rule = Str::snake(str_replace('validate', '', $possibleMethod));
|
||||
|
||||
return "Did you mean `{$rule}` ?";
|
||||
}
|
||||
|
||||
protected function getMethodFromExceptionMessage(string $message): ?string
|
||||
{
|
||||
if (! preg_match(self::REGEX, $message, $matches)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $matches['method'];
|
||||
}
|
||||
|
||||
protected function getAvailableMethods(): Collection
|
||||
{
|
||||
$class = new ReflectionClass(Validator::class);
|
||||
|
||||
$extensions = Collection::make((app('validator')->make([], []))->extensions)
|
||||
->keys()
|
||||
->map(function (string $extension) {
|
||||
return 'validate'.Str::studly($extension);
|
||||
});
|
||||
|
||||
return Collection::make($class->getMethods())
|
||||
->filter(function (ReflectionMethod $method) {
|
||||
return preg_match('/(validate(?!(Attribute|UsingCustomRule))[A-Z][a-zA-Z]+)/', $method->name);
|
||||
})
|
||||
->map(function (ReflectionMethod $method) {
|
||||
return $method->name;
|
||||
})
|
||||
->merge($extensions);
|
||||
}
|
||||
}
|
||||
117
vendor/facade/ignition/src/SolutionProviders/ViewNotFoundSolutionProvider.php
vendored
Normal file
117
vendor/facade/ignition/src/SolutionProviders/ViewNotFoundSolutionProvider.php
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
<?php
|
||||
|
||||
namespace Facade\Ignition\SolutionProviders;
|
||||
|
||||
use Facade\Ignition\Exceptions\ViewException;
|
||||
use Facade\Ignition\Support\StringComparator;
|
||||
use Facade\IgnitionContracts\BaseSolution;
|
||||
use Facade\IgnitionContracts\HasSolutionsForThrowable;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\View;
|
||||
use InvalidArgumentException;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
use Symfony\Component\Finder\SplFileInfo;
|
||||
use Throwable;
|
||||
|
||||
class ViewNotFoundSolutionProvider implements HasSolutionsForThrowable
|
||||
{
|
||||
protected const REGEX = '/View \[(.*)\] not found/m';
|
||||
|
||||
public function canSolve(Throwable $throwable): bool
|
||||
{
|
||||
if (! $throwable instanceof InvalidArgumentException && ! $throwable instanceof ViewException) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (bool)preg_match(self::REGEX, $throwable->getMessage(), $matches);
|
||||
}
|
||||
|
||||
public function getSolutions(Throwable $throwable): array
|
||||
{
|
||||
preg_match(self::REGEX, $throwable->getMessage(), $matches);
|
||||
|
||||
$missingView = $matches[1] ?? null;
|
||||
|
||||
$suggestedView = $this->findRelatedView($missingView);
|
||||
|
||||
if ($suggestedView) {
|
||||
return [
|
||||
BaseSolution::create("{$missingView} was not found.")
|
||||
->setSolutionDescription("Did you mean `{$suggestedView}`?"),
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
BaseSolution::create("{$missingView} was not found.")
|
||||
->setSolutionDescription('Are you sure the view exists and is a `.blade.php` file?'),
|
||||
];
|
||||
}
|
||||
|
||||
protected function findRelatedView(string $missingView): ?string
|
||||
{
|
||||
$views = $this->getAllViews();
|
||||
|
||||
return StringComparator::findClosestMatch($views, $missingView);
|
||||
}
|
||||
|
||||
protected function getAllViews(): array
|
||||
{
|
||||
/** @var \Illuminate\View\FileViewFinder $fileViewFinder */
|
||||
$fileViewFinder = View::getFinder();
|
||||
|
||||
$extensions = $fileViewFinder->getExtensions();
|
||||
|
||||
$viewsForHints = collect($fileViewFinder->getHints())
|
||||
->flatMap(function ($paths, string $namespace) use ($extensions) {
|
||||
$paths = Arr::wrap($paths);
|
||||
|
||||
return collect($paths)
|
||||
->flatMap(function (string $path) use ($extensions) {
|
||||
return $this->getViewsInPath($path, $extensions);
|
||||
})
|
||||
->map(function (string $view) use ($namespace) {
|
||||
return "{$namespace}::{$view}";
|
||||
})
|
||||
->toArray();
|
||||
});
|
||||
|
||||
$viewsForViewPaths = collect($fileViewFinder->getPaths())
|
||||
->flatMap(function (string $path) use ($extensions) {
|
||||
return $this->getViewsInPath($path, $extensions);
|
||||
});
|
||||
|
||||
return $viewsForHints->merge($viewsForViewPaths)->toArray();
|
||||
}
|
||||
|
||||
protected function getViewsInPath(string $path, array $extensions): array
|
||||
{
|
||||
$filePatterns = array_map(function (string $extension) {
|
||||
return "*.{$extension}";
|
||||
}, $extensions);
|
||||
|
||||
$extensionsWithDots = array_map(function (string $extension) {
|
||||
return ".{$extension}";
|
||||
}, $extensions);
|
||||
|
||||
$files = (new Finder())
|
||||
->in($path)
|
||||
->files();
|
||||
|
||||
foreach ($filePatterns as $filePattern) {
|
||||
$files->name($filePattern);
|
||||
}
|
||||
|
||||
$views = [];
|
||||
|
||||
foreach ($files as $file) {
|
||||
if ($file instanceof SplFileInfo) {
|
||||
$view = $file->getRelativePathname();
|
||||
$view = str_replace($extensionsWithDots, '', $view);
|
||||
$view = str_replace('/', '.', $view);
|
||||
$views[] = $view;
|
||||
}
|
||||
}
|
||||
|
||||
return $views;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user