Passed
Push — master ( b62344...459625 )
by Alexander
01:46
created

SchemaRenderer::renderRelationOption()   B

Complexity

Conditions 7
Paths 4

Size

Total Lines 16
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 7

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 10
c 1
b 0
f 0
dl 0
loc 16
ccs 11
cts 11
cp 1
rs 8.8333
cc 7
nc 4
nop 2
crap 7
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Yii\Cycle\Schema\Converter\SchemaToPHP;
6
7
use Cycle\ORM\Relation;
8
use Cycle\ORM\Schema;
9
use Cycle\ORM\SchemaInterface;
10
use Cycle\Schema\Relation\RelationSchema;
11
12
final class SchemaRenderer
13
{
14
    private const RELATION = [
15
        Relation::HAS_ONE => 'Relation::HAS_ONE',
16
        Relation::HAS_MANY => 'Relation::HAS_MANY',
17
        Relation::BELONGS_TO => 'Relation::BELONGS_TO',
18
        Relation::REFERS_TO => 'Relation::REFERS_TO',
19
        Relation::MANY_TO_MANY => 'Relation::MANY_TO_MANY',
20
        Relation::BELONGS_TO_MORPHED => 'Relation::BELONGS_TO_MORPHED',
21
        Relation::MORPHED_HAS_ONE => 'Relation::MORPHED_HAS_ONE',
22
        Relation::MORPHED_HAS_MANY => 'Relation::MORPHED_HAS_MANY',
23
    ];
24
    private const RELATION_OPTION = [
25
        Relation::MORPH_KEY => 'Relation::MORPH_KEY',
26
        Relation::CASCADE => 'Relation::CASCADE',
27
        Relation::NULLABLE => 'Relation::NULLABLE',
28
        Relation::OUTER_KEY => 'Relation::OUTER_KEY',
29
        Relation::INNER_KEY => 'Relation::INNER_KEY',
30
        Relation::WHERE => 'Relation::WHERE',
31
        Relation::THROUGH_INNER_KEY => 'Relation::THROUGH_INNER_KEY',
32
        Relation::THROUGH_OUTER_KEY => 'Relation::THROUGH_OUTER_KEY',
33
        Relation::THROUGH_ENTITY => 'Relation::THROUGH_ENTITY',
34
        Relation::THROUGH_WHERE => 'Relation::THROUGH_WHERE',
35
        RelationSchema::INDEX_CREATE => 'RelationSchema::INDEX_CREATE',
36
        RelationSchema::FK_CREATE => 'RelationSchema::FK_CREATE',
37
        RelationSchema::FK_ACTION => 'RelationSchema::FK_ACTION',
38
        RelationSchema::INVERSE => 'RelationSchema::INVERSE',
39
        RelationSchema::MORPH_KEY_LENGTH => 'RelationSchema::MORPH_KEY_LENGTH',
40
    ];
41
    private const PREFETCH_MODE = [
42
        Relation::LOAD_PROMISE => 'Relation::LOAD_PROMISE',
43
        Relation::LOAD_EAGER => 'Relation::LOAD_EAGER',
44
    ];
45
    private const GENERAL_OPTION = [
46
        Relation::TYPE => 'Relation::TYPE',
47
        Relation::TARGET => 'Relation::TARGET',
48
        Relation::SCHEMA => 'Relation::SCHEMA',
49
        Relation::LOAD => 'Relation::LOAD',
50
    ];
51
52
    private SchemaInterface $schema;
53
54 2
    public function __construct(SchemaInterface $schema)
55
    {
56 2
        $this->schema = $schema;
57 2
    }
58
59 2
    public function render(): string
60
    {
61 2
        $arrayToString = new ArrayItemExporter(null);
62 2
        foreach ($this->schema->getRoles() as $role) {
63 1
            $arrayToString->value[] = $this->renderRole($role);
64
        }
65 2
        return (string)$arrayToString;
66
    }
67
68 1
    private function renderRole(string $role): ?ArrayItemExporter
69
    {
70 1
        $aliasOf = $this->schema->resolveAlias($role);
71 1
        if ($aliasOf !== null && $aliasOf !== $role) {
72
            // This role is an alias
73
            return null;
74
        }
75 1
        if ($this->schema->defines($role) === false) {
76
            // Role has no definition within the schema
77
            return null;
78
        }
79 1
        return new ArrayItemExporter($role, [
80 1
            $this->renderDatabase($role),
81 1
            $this->renderTable($role),
82 1
            $this->renderEntity($role),
83 1
            $this->renderMapper($role),
84 1
            $this->renderRepository($role),
85 1
            $this->renderScope($role),
86 1
            $this->renderPK($role),
87 1
            $this->renderFields($role),
88 1
            $this->renderTypecast($role),
89 1
            $this->renderRelations($role),
90 1
        ], true);
91
    }
92 1
    private function renderDatabase(string $role): ArrayItemExporter
93
    {
94 1
        return new ArrayItemExporter('Schema::DATABASE', $this->schema->define($role, Schema::DATABASE));
95
    }
96 1
    private function renderTable(string $role): ArrayItemExporter
97
    {
98 1
        return new ArrayItemExporter('Schema::TABLE', $this->schema->define($role, Schema::TABLE));
99
    }
100 1
    private function renderEntity(string $role): ArrayItemExporter
101
    {
102 1
        return new ArrayItemExporter('Schema::ENTITY', $this->schema->define($role, Schema::ENTITY));
103
    }
104 1
    private function renderMapper(string $role): ArrayItemExporter
105
    {
106 1
        return new ArrayItemExporter('Schema::MAPPER', $this->schema->define($role, Schema::MAPPER));
107
    }
108 1
    private function renderRepository(string $role): ArrayItemExporter
109
    {
110 1
        return new ArrayItemExporter('Schema::REPOSITORY', $this->schema->define($role, Schema::REPOSITORY));
111
    }
112 1
    private function renderScope(string $role): ArrayItemExporter
113
    {
114 1
        return new ArrayItemExporter('Schema::CONSTRAIN', $this->schema->define($role, Schema::CONSTRAIN));
115
    }
116 1
    private function renderPK(string $role): ArrayItemExporter
117
    {
118 1
        return new ArrayItemExporter('Schema::PRIMARY_KEY', $this->schema->define($role, Schema::PRIMARY_KEY));
119
    }
120 1
    private function renderFields(string $role): ArrayItemExporter
121
    {
122 1
        return new ArrayItemExporter('Schema::COLUMNS', $this->schema->define($role, Schema::COLUMNS));
123
    }
124 1
    private function renderTypecast(string $role): ArrayItemExporter
125
    {
126 1
        return new ArrayItemExporter('Schema::TYPECAST', $this->schema->define($role, Schema::TYPECAST));
127
    }
128 1
    private function renderRelations(string $role): ArrayItemExporter
129
    {
130 1
        $relations = $this->schema->define($role, Schema::RELATIONS);
131 1
        $results = [];
132 1
        foreach ($relations as $field => $relation) {
133 1
            $relationResult = [];
134 1
            foreach ($relation as $option => $value) {
135 1
                $relationResult[] = $this->renderRelationOption($option, $value);
136
            }
137 1
            $results[] = new ArrayItemExporter($field, $relationResult, true);
138
        }
139 1
        return new ArrayItemExporter('Schema::RELATIONS', $results);
140
    }
141 1
    private function renderRelationOption(int $option, $value): ArrayItemExporter
142
    {
143 1
        $item = new ArrayItemExporter(self::GENERAL_OPTION[$option] ?? (string)$option, $value);
144
145
        // replace numeric keys and values with constants
146 1
        if ($option === Relation::LOAD && array_key_exists($value, self::PREFETCH_MODE)) {
147 1
            $item->value = self::PREFETCH_MODE[$value];
148 1
            $item->wrapValue = false;
149 1
        } elseif ($option === Relation::TYPE && array_key_exists($value, self::RELATION)) {
150 1
            $item->value = self::RELATION[$value];
151 1
            $item->wrapValue = false;
152 1
        } elseif ($option === Relation::SCHEMA && is_array($value)) {
153 1
            $item->value = $this->renderRelationSchemaKeys($value);
154
        }
155
156 1
        return $item;
157
    }
158 1
    private function renderRelationSchemaKeys(array $value): array
159
    {
160 1
        $result = [];
161 1
        foreach ($value as $listKey => $listValue) {
162 1
            $result[] = new ArrayItemExporter(
163 1
                array_key_exists($listKey, self::RELATION_OPTION) ? self::RELATION_OPTION[$listKey] : (string)$listKey,
164
                $listValue
165
            );
166
        }
167 1
        return $result;
168
    }
169
}
170