Issues (20)

src/Compiler.php (3 issues)

Labels
Severity
1
<?php
2
3
/**
4
 * Cycle ORM Schema Builder.
5
 *
6
 * @license   MIT
7
 * @author    Anton Titov (Wolfy-J)
8
 */
9
10
declare(strict_types=1);
11
12
namespace Cycle\Schema;
13
14
use Cycle\ORM\Mapper\Mapper;
15
use Cycle\ORM\Schema;
16
use Cycle\ORM\Select\Repository;
17
use Cycle\ORM\Select\Source;
18
use Cycle\Schema\Definition\Entity;
19
use Doctrine\Common\Inflector\Inflector;
20
use Spiral\Database\Exception\CompilerException;
21
22
final class Compiler
23
{
24
    /** @var array */
25
    private $result = [];
26
27
    /** @var array */
28
    private $defaults = [
29
        Schema::MAPPER => Mapper::class,
30
        Schema::REPOSITORY => Repository::class,
31
        Schema::SOURCE => Source::class,
32
        Schema::CONSTRAIN => null,
33
    ];
34
35
    /**
36
     * Compile the registry schema.
37
     *
38
     * @param Registry $registry
39
     * @param GeneratorInterface[] $generators
40
     * @param array $defaults
41
     * @return array
42
     *
43
     */
44
    public function compile(Registry $registry, array $generators = [], array $defaults = []): array
45
    {
46
        $this->defaults = $defaults + $this->defaults;
47
48
        foreach ($generators as $generator) {
49
            if (!$generator instanceof GeneratorInterface) {
50
                throw new CompilerException(sprintf(
51
                    'Invalid generator `%s`',
52
                    is_object($generator) ? get_class($generator) : gettype($generator)
53
                ));
54
            }
55
56
            $registry = $generator->run($registry);
57
        }
58
59
        foreach ($registry->getIterator() as $entity) {
60
            if ($this->getPrimary($entity) === null) {
0 ignored issues
show
Are you sure the usage of $this->getPrimary($entity) targeting Cycle\Schema\Compiler::getPrimary() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
61
                // incomplete entity, skip
62
                continue;
63
            }
64
65
            $this->compute($registry, $entity);
66
        }
67
68
        return $this->result;
69
    }
70
71
    /**
72
     * Get compiled schema result.
73
     *
74
     * @return array
75
     */
76
    public function getSchema(): array
77
    {
78
        return $this->result;
79
    }
80
81
    /**
82
     * Compile entity and relation definitions into packed ORM schema.
83
     *
84
     * @param Registry $registry
85
     * @param Entity   $entity
86
     */
87
    protected function compute(Registry $registry, Entity $entity): void
88
    {
89
        $schema = [
90
            Schema::ENTITY       => $entity->getClass(),
91
            Schema::SOURCE       => $entity->getSource() ?? $this->defaults[Schema::SOURCE],
92
            Schema::MAPPER       => $entity->getMapper() ?? $this->defaults[Schema::MAPPER],
93
            Schema::REPOSITORY   => $entity->getRepository() ?? $this->defaults[Schema::REPOSITORY],
94
            Schema::CONSTRAIN    => $entity->getConstrain() ?? $this->defaults[Schema::CONSTRAIN],
95
            Schema::SCHEMA       => $entity->getSchema(),
96
            Schema::PRIMARY_KEY  => $this->getPrimary($entity),
0 ignored issues
show
Are you sure the usage of $this->getPrimary($entity) targeting Cycle\Schema\Compiler::getPrimary() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
97
            Schema::COLUMNS      => $this->renderColumns($entity),
98
            Schema::FIND_BY_KEYS => $this->renderReferences($entity),
99
            Schema::TYPECAST     => $this->renderTypecast($entity),
100
            Schema::RELATIONS    => $this->renderRelations($registry, $entity)
101
        ];
102
103
        if ($registry->hasTable($entity)) {
104
            $schema[Schema::DATABASE] = $registry->getDatabase($entity);
105
            $schema[Schema::TABLE] = $registry->getTable($entity);
106
        }
107
108
        // table inheritance
109
        foreach ($registry->getChildren($entity) as $child) {
110
            $this->result[$child->getClass()] = [Schema::ROLE => $entity->getRole()];
111
            $schema[Schema::CHILDREN][$this->childAlias($child)] = $child->getClass();
112
        }
113
114
        ksort($schema);
115
        $this->result[$entity->getRole()] = $schema;
116
    }
117
118
    /**
119
     * @param Entity $entity
120
     * @return array
121
     */
122
    protected function renderColumns(Entity $entity): array
123
    {
124
        $schema = [];
125
        foreach ($entity->getFields() as $name => $field) {
126
            $schema[$name] = $field->getColumn();
127
        }
128
129
        return $schema;
130
    }
131
132
    /**
133
     * @param Entity $entity
134
     * @return array
135
     */
136
    protected function renderTypecast(Entity $entity): array
137
    {
138
        $schema = [];
139
        foreach ($entity->getFields() as $name => $field) {
140
            if ($field->hasTypecast()) {
141
                $schema[$name] = $field->getTypecast();
142
            }
143
        }
144
145
        return $schema;
146
    }
147
148
    /**
149
     * @param Entity $entity
150
     * @return array
151
     */
152
    protected function renderReferences(Entity $entity): array
153
    {
154
        $schema = [$this->getPrimary($entity)];
0 ignored issues
show
Are you sure the usage of $this->getPrimary($entity) targeting Cycle\Schema\Compiler::getPrimary() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
155
156
        foreach ($entity->getFields() as $name => $field) {
157
            if ($field->isReferenced()) {
158
                $schema[] = $name;
159
            }
160
        }
161
162
        return array_unique($schema);
163
    }
164
165
    /**
166
     * @param Registry $registry
167
     * @param Entity   $entity
168
     * @return array
169
     */
170
    protected function renderRelations(Registry $registry, Entity $entity): array
171
    {
172
        $result = [];
173
        foreach ($registry->getRelations($entity) as $name => $relation) {
174
            $result[$name] = $relation->packSchema();
175
        }
176
177
        return $result;
178
    }
179
180
    /**
181
     * @param Entity $entity
182
     * @return string|null
183
     */
184
    protected function getPrimary(Entity $entity): ?string
185
    {
186
        foreach ($entity->getFields() as $name => $field) {
187
            if ($field->isPrimary()) {
188
                return $name;
189
            }
190
        }
191
192
        return null;
193
    }
194
195
    /**
196
     * Return the unique alias for the child entity.
197
     *
198
     * @param Entity $entity
199
     * @return string
200
     */
201
    protected function childAlias(Entity $entity): string
202
    {
203
        $r = new \ReflectionClass($entity->getClass());
204
        return Inflector::classify($r->getShortName());
205
    }
206
}
207