Completed
Push — master ( 9060d6...83d0c7 )
by Anton
02:51
created

Entities::run()   B

Complexity

Conditions 6
Paths 10

Size

Total Lines 48
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 24
dl 0
loc 48
rs 8.9137
c 0
b 0
f 0
cc 6
nc 10
nop 1
1
<?php declare(strict_types=1);
2
/**
3
 * Spiral Framework.
4
 *
5
 * @license   MIT
6
 * @author    Anton Titov (Wolfy-J)
7
 */
8
9
namespace Cycle\Annotated;
10
11
use Cycle\Annotated\Annotation\Entity;
12
use Cycle\Schema\Definition\Entity as EntitySchema;
13
use Cycle\Schema\GeneratorInterface;
14
use Cycle\Schema\Registry;
15
use Doctrine\Common\Inflector\Inflector;
16
use Spiral\Annotations\Parser;
17
use Spiral\Tokenizer\ClassesInterface;
18
19
/**
20
 * Generates ORM schema based on annotated classes.
21
 */
22
final class Entities implements GeneratorInterface
23
{
24
    /** @var ClassesInterface */
25
    private $locator;
26
27
    /** @var Parser */
28
    private $parser;
29
30
    /** @var Generator */
31
    private $generator;
32
33
    /**
34
     * @param ClassesInterface $locator
35
     * @param Parser           $parser
36
     */
37
    public function __construct(ClassesInterface $locator, Parser $parser)
38
    {
39
        $this->locator = $locator;
40
        $this->parser = $parser;
41
        $this->generator = new Generator($parser);
42
    }
43
44
    /**
45
     * @param Registry $registry
46
     * @return Registry
47
     */
48
    public function run(Registry $registry): Registry
49
    {
50
        /** @var EntitySchema[] $children */
51
        $children = [];
52
        foreach ($this->locator->getClasses() as $class) {
53
            if ($class->getDocComment() === false) {
54
                continue;
55
            }
56
57
            $ann = $this->parser->parse($class->getDocComment());
58
            if (!isset($ann[Entity::NAME])) {
59
                continue;
60
            }
61
62
            /** @var Entity $ea */
63
            $ea = $ann[Entity::NAME];
64
65
            $e = $this->generator->initEntity($ea, $class);
66
67
            // columns
68
            $this->generator->initFields($e, $class);
69
70
            // relations
71
            $this->generator->initRelations($e, $class);
72
73
            if ($this->hasParent($registry, $e->getClass())) {
0 ignored issues
show
Bug introduced by
It seems like $e->getClass() can also be of type null; however, parameter $class of Cycle\Annotated\Entities::hasParent() does only seem to accept string, 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 ignore-type  annotation

73
            if ($this->hasParent($registry, /** @scrutinizer ignore-type */ $e->getClass())) {
Loading history...
74
                $children[] = $e;
75
                continue;
76
            }
77
78
            // register entity (OR find parent)
79
            $registry->register($e);
80
81
            $registry->linkTable(
82
                $e,
83
                $ea->getDatabase(),
84
                $ea->getTable() ?? $this->tableName($e->getRole())
85
            );
86
        }
87
88
        foreach ($children as $e) {
89
            $registry->registerChild(
90
                $registry->getEntity($this->findParent($registry, $e->getClass())),
0 ignored issues
show
Bug introduced by
It seems like $this->findParent($registry, $e->getClass()) can also be of type null; however, parameter $role of Cycle\Schema\Registry::getEntity() does only seem to accept string, 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 ignore-type  annotation

90
                $registry->getEntity(/** @scrutinizer ignore-type */ $this->findParent($registry, $e->getClass())),
Loading history...
91
                $e
92
            );
93
        }
94
95
        return $registry;
96
    }
97
98
    /**
99
     * @param string $role
100
     * @return string
101
     */
102
    protected function tableName(string $role): string
103
    {
104
        return Inflector::pluralize(Inflector::tableize($role));
105
    }
106
107
    /**
108
     * @param Registry $registry
109
     * @param string   $class
110
     * @return bool
111
     */
112
    protected function hasParent(Registry $registry, string $class): bool
113
    {
114
        return $this->findParent($registry, $class) !== null;
115
    }
116
117
    /**
118
     * @param Registry $registry
119
     * @param string   $class
120
     * @return string|null
121
     */
122
    protected function findParent(Registry $registry, string $class): ?string
0 ignored issues
show
Unused Code introduced by
The parameter $registry is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

122
    protected function findParent(/** @scrutinizer ignore-unused */ Registry $registry, string $class): ?string

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
123
    {
124
        $parents = class_parents($class);
125
        foreach (array_reverse($parents) as $parent) {
126
            $class = new \ReflectionClass($parent);
127
            if ($class->getDocComment() === false) {
128
                continue;
129
            }
130
131
            $ann = $this->parser->parse($class->getDocComment());
0 ignored issues
show
Bug introduced by
It seems like $class->getDocComment() can also be of type true; however, parameter $body of Spiral\Annotations\Parser::parse() does only seem to accept string, 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 ignore-type  annotation

131
            $ann = $this->parser->parse(/** @scrutinizer ignore-type */ $class->getDocComment());
Loading history...
132
            if (isset($ann[Entity::NAME])) {
133
                return $parent;
134
            }
135
        }
136
137
        return null;
138
    }
139
}