Completed
Push — master ( c87e7f...53c2c8 )
by Marcel
07:32
created

ModelFinder::getModelsInDirectory()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 10
rs 9.9332
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
3
namespace BeyondCode\ErdGenerator;
4
5
use PhpParser\NodeTraverser;
6
use PhpParser\ParserFactory;
7
use PhpParser\Node\Stmt\Class_;
8
use Illuminate\Support\Collection;
9
use Illuminate\Filesystem\Filesystem;
10
use PhpParser\NodeVisitor\NameResolver;
11
use Illuminate\Database\Eloquent\Model as EloquentModel;
12
13
class ModelFinder
14
{
15
16
    /** @var Filesystem */
17
    protected $filesystem;
18
19
    public function __construct(Filesystem $filesystem)
20
    {
21
        $this->filesystem = $filesystem;
22
    }
23
24
    public function getModelsInDirectory(string $directory): Collection
25
    {
26
        return Collection::make($this->filesystem->files($directory))->map(function ($path) {
27
            return $this->getFullyQualifiedClassNameFromFile($path);
28
        })->filter(function (string $className) {
29
            return !empty($className);
30
        })->filter(function (string $className) {
31
            return is_subclass_of($className, EloquentModel::class);
32
        });
33
    }
34
35
    protected function getFullyQualifiedClassNameFromFile(string $path): string
36
    {
37
        $parser = (new ParserFactory())->create(ParserFactory::PREFER_PHP7);
38
39
        $traverser = new NodeTraverser();
40
        $traverser->addVisitor(new NameResolver());
41
42
        $code = file_get_contents($path);
43
44
        $statements = $parser->parse($code);
45
46
        $statements = $traverser->traverse($statements);
0 ignored issues
show
Bug introduced by
It seems like $statements can also be of type null; however, PhpParser\NodeTraverser::traverse() does only seem to accept array<integer,object<PhpParser\Node>>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
47
48
        return collect($statements[0]->stmts)
0 ignored issues
show
Bug introduced by
Accessing stmts on the interface PhpParser\Node 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...
49
                ->filter(function ($statement) {
50
                    return $statement instanceof Class_;
51
                })
52
                ->map(function (Class_ $statement) {
53
                    return $statement->namespacedName->toString();
54
                })
55
                ->first() ?? '';
56
    }
57
    
58
}