beyondcode /
laravel-er-diagram-generator
| 1 | <?php |
||||
| 2 | |||||
| 3 | namespace BeyondCode\ErdGenerator; |
||||
| 4 | |||||
| 5 | use Illuminate\Database\Eloquent\Model as EloquentModel; |
||||
| 6 | use Illuminate\Filesystem\Filesystem; |
||||
| 7 | use Illuminate\Support\Collection; |
||||
| 8 | use Illuminate\Support\Str; |
||||
| 9 | use PhpParser\Node\Stmt\Class_; |
||||
| 10 | use PhpParser\Node\Stmt\Namespace_; |
||||
| 11 | use PhpParser\NodeTraverser; |
||||
| 12 | use PhpParser\NodeVisitor\NameResolver; |
||||
| 13 | use PhpParser\ParserFactory; |
||||
| 14 | use ReflectionClass; |
||||
| 15 | |||||
| 16 | class ModelFinder |
||||
| 17 | { |
||||
| 18 | |||||
| 19 | /** @var Filesystem */ |
||||
| 20 | protected $filesystem; |
||||
| 21 | |||||
| 22 | public function __construct(Filesystem $filesystem) |
||||
| 23 | { |
||||
| 24 | $this->filesystem = $filesystem; |
||||
| 25 | } |
||||
| 26 | |||||
| 27 | public function getModelsInDirectory(string $directory): Collection |
||||
| 28 | { |
||||
| 29 | $files = config('erd-generator.recursive') ? |
||||
| 30 | $this->filesystem->allFiles($directory) : |
||||
| 31 | $this->filesystem->files($directory); |
||||
| 32 | |||||
| 33 | $ignoreModels = array_filter(config('erd-generator.ignore', []), 'is_string'); |
||||
| 34 | $whitelistModels = array_filter(config('erd-generator.whitelist', []), 'is_string'); |
||||
| 35 | |||||
| 36 | $collection = Collection::make($files)->filter(function ($path) { |
||||
|
0 ignored issues
–
show
Bug
introduced
by
Loading history...
|
|||||
| 37 | return Str::endsWith($path, '.php'); |
||||
| 38 | })->map(function ($path) { |
||||
| 39 | return $this->getFullyQualifiedClassNameFromFile($path); |
||||
| 40 | })->filter(function (string $className) { |
||||
| 41 | return !empty($className) |
||||
| 42 | && is_subclass_of($className, EloquentModel::class) |
||||
| 43 | && ! (new ReflectionClass($className))->isAbstract(); |
||||
| 44 | }); |
||||
| 45 | |||||
| 46 | if(!count($whitelistModels)) { |
||||
| 47 | return $collection->diff($ignoreModels)->sort(); |
||||
|
0 ignored issues
–
show
$ignoreModels of type array is incompatible with the type Illuminate\Contracts\Support\Arrayable expected by parameter $items of Illuminate\Support\Collection::diff().
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||
| 48 | } |
||||
| 49 | |||||
| 50 | return $collection->filter(function (string $className) use ($whitelistModels) { |
||||
| 51 | return in_array($className, $whitelistModels); |
||||
| 52 | }); |
||||
| 53 | } |
||||
| 54 | |||||
| 55 | protected function getFullyQualifiedClassNameFromFile(string $path): string |
||||
| 56 | { |
||||
| 57 | $factory = new ParserFactory(); |
||||
| 58 | $parser = method_exists($factory, 'createForHostVersion') |
||||
| 59 | ? $factory->createForHostVersion() |
||||
| 60 | : $factory->create(ParserFactory::PREFER_PHP7); |
||||
|
0 ignored issues
–
show
The method
create() does not exist on PhpParser\ParserFactory. Did you maybe mean createForNewestSupportedVersion()?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces. This is most likely a typographical error or the method has been renamed. Loading history...
|
|||||
| 61 | |||||
| 62 | $traverser = new NodeTraverser(); |
||||
| 63 | $traverser->addVisitor(new NameResolver()); |
||||
| 64 | |||||
| 65 | $code = file_get_contents($path); |
||||
| 66 | |||||
| 67 | $statements = $parser->parse($code); |
||||
| 68 | $statements = $traverser->traverse($statements); |
||||
|
0 ignored issues
–
show
It seems like
$statements can also be of type null; however, parameter $nodes of PhpParser\NodeTraverser::traverse() does only seem to accept array, maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||
| 69 | |||||
| 70 | // get the first namespace declaration in the file |
||||
| 71 | $root_statement = collect($statements)->first(function ($statement) { |
||||
|
0 ignored issues
–
show
$statements of type array is incompatible with the type Illuminate\Contracts\Support\Arrayable expected by parameter $value of collect().
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||
| 72 | return $statement instanceof Namespace_; |
||||
| 73 | }); |
||||
| 74 | |||||
| 75 | if (! $root_statement) { |
||||
| 76 | return ''; |
||||
| 77 | } |
||||
| 78 | |||||
| 79 | return collect($root_statement->stmts) |
||||
| 80 | ->filter(function ($statement) { |
||||
| 81 | return $statement instanceof Class_; |
||||
| 82 | }) |
||||
| 83 | ->map(function (Class_ $statement) { |
||||
| 84 | return $statement->namespacedName->toString(); |
||||
|
0 ignored issues
–
show
The method
toString() does not exist on null.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces. This is most likely a typographical error or the method has been renamed. Loading history...
|
|||||
| 85 | }) |
||||
| 86 | ->first() ?? ''; |
||||
| 87 | } |
||||
| 88 | } |
||||
| 89 |