Completed
Branch feature/pre-split (60f5c0)
by Anton
03:19
created

RecordSchema   A

Complexity

Total Complexity 25

Size/Duplication

Total Lines 218
Duplicated Lines 5.5 %

Coupling/Cohesion

Components 1
Dependencies 5

Importance

Changes 0
Metric Value
dl 12
loc 218
rs 10
c 0
b 0
f 0
wmc 25
lcom 1
cbo 5

14 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 9 1
A getClass() 0 4 1
A getReflection() 0 4 1
A getInstantiator() 0 4 1
A getDatabase() 0 10 2
A getTable() 0 11 2
A getIndexes() 0 8 2
A defineTable() 0 8 1
A getRelations() 0 4 1
A packSchema() 0 4 1
A getFields() 12 12 3
A isRelation() 0 8 2
B castIndex() 0 28 6
A createDefaults() 0 5 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
/**
3
 * components
4
 *
5
 * @author    Wolfy-J
6
 */
7
namespace Spiral\ORM\Schemas;
8
9
use Doctrine\Common\Inflector\Inflector;
10
use Spiral\Database\Schemas\Prototypes\AbstractTable;
11
use Spiral\Models\Reflections\ReflectionEntity;
12
use Spiral\ORM\Configs\MutatorsConfig;
13
use Spiral\ORM\Entities\RecordInstantiator;
14
use Spiral\ORM\Exceptions\DefinitionException;
15
use Spiral\ORM\Helpers\ColumnRenderer;
16
use Spiral\ORM\Record;
17
use Spiral\ORM\Schemas\Definitions\IndexDefinition;
18
19
class RecordSchema implements SchemaInterface
20
{
21
    /**
22
     * @var ReflectionEntity
23
     */
24
    private $reflection;
25
26
    /**
27
     * @invisible
28
     * @var MutatorsConfig
29
     */
30
    private $mutatorsConfig;
31
32
    /**
33
     * @var ColumnRenderer
34
     */
35
    private $renderer;
36
37
    /**
38
     * @param ReflectionEntity    $reflection
39
     * @param MutatorsConfig      $mutators
40
     * @param ColumnRenderer|null $rendered
41
     */
42
    public function __construct(
43
        ReflectionEntity $reflection,
44
        MutatorsConfig $mutators,
45
        ColumnRenderer $rendered = null
46
    ) {
47
        $this->reflection = $reflection;
48
        $this->mutatorsConfig = $mutators;
49
        $this->renderer = $rendered ?? new ColumnRenderer();
50
    }
51
52
    /**
53
     * {@inheritdoc}
54
     */
55
    public function getClass(): string
56
    {
57
        return $this->reflection->getName();
58
    }
59
60
    /**
61
     * @return ReflectionEntity
62
     */
63
    public function getReflection(): ReflectionEntity
64
    {
65
        return $this->reflection;
66
    }
67
68
    /**
69
     * {@inheritdoc}
70
     */
71
    public function getInstantiator(): string
72
    {
73
        return $this->reflection->getProperty('instantiator') ?? RecordInstantiator::class;
74
    }
75
76
    /**
77
     * {@inheritdoc}
78
     */
79
    public function getDatabase()
80
    {
81
        $database = $this->reflection->getProperty('database');
82
        if (empty($database)) {
83
            //Empty database to be used
84
            return null;
85
        }
86
87
        return $database;
88
    }
89
90
    /**
91
     * {@inheritdoc}
92
     */
93
    public function getTable(): string
94
    {
95
        $table = $this->reflection->getProperty('table');
96
        if (empty($table)) {
97
            //Generate collection using short class name
98
            $table = Inflector::camelize($this->reflection->getShortName());
99
            $table = Inflector::pluralize($table);
100
        }
101
102
        return $table;
103
    }
104
105
    /**
106
     * Returns set of declared indexes.
107
     *
108
     * Example:
109
     * const INDEXES = [
110
     *      [self::UNIQUE, 'email'],
111
     *      [self::INDEX, 'status', 'balance'],
112
     *      [self::INDEX, 'public_id']
113
     * ];
114
     *
115
     * @do generator
116
     *
117
     * @return \Generator|IndexDefinition[]
118
     *
119
     * @throws DefinitionException
120
     */
121
    public function getIndexes(): \Generator
122
    {
123
        $definitions = $this->reflection->getProperty('indexes') ?? [];
124
125
        foreach ($definitions as $definition) {
126
            yield $this->castIndex($definition);
127
        }
128
    }
129
130
    /**
131
     * {@inheritdoc}
132
     */
133
    public function defineTable(AbstractTable $table): AbstractTable
134
    {
135
        return $this->renderer->renderColumns(
136
            $this->getFields(),
137
            $this->createDefaults(),
138
            $table
139
        );
140
    }
141
142
    /**
143
     * {@inheritdoc}
144
     */
145
    public function getRelations(): array
146
    {
147
        return [];
148
    }
149
150
    /**
151
     * {@inheritdoc}
152
     */
153
    public function packSchema(SchemaBuilder $builder, AbstractTable $table = null): array
154
    {
155
        return [];
156
    }
157
158
    /**
159
     * {@inheritdoc}
160
     */
161 View Code Duplication
    protected function getFields(): array
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
162
    {
163
        $fields = $this->reflection->getFields();
164
165
        foreach ($fields as $field => $type) {
166
            if ($this->isRelation($type)) {
167
                unset($fields[$field]);
168
            }
169
        }
170
171
        return $fields;
172
    }
173
174
    /**
175
     * Check if field schema/type defines relation.
176
     *
177
     * @param mixed $type
178
     *
179
     * @return bool
180
     */
181
    protected function isRelation($type): bool
182
    {
183
        if (is_array($type)) {
184
            return true;
185
        }
186
187
        return false;
188
    }
189
190
    /**
191
     * @param array $definition
192
     *
193
     * @return IndexDefinition
194
     *
195
     * @throws DefinitionException
196
     */
197
    protected function castIndex(array $definition)
198
    {
199
        $unique = null;
200
        $columns = [];
201
202
        foreach ($definition as $chunk) {
203
            if ($chunk == Record::INDEX || $chunk == Record::UNIQUE) {
204
                $unique = $chunk === Record::UNIQUE;
205
                continue;
206
            }
207
208
            $columns[] = $chunk;
209
        }
210
211
        if (is_null($unique)) {
212
            throw new DefinitionException(
213
                "Record '{$this}' has index definition with unspecified index type"
214
            );
215
        }
216
217
        if (empty($columns)) {
218
            throw new DefinitionException(
219
                "Record '{$this}' has index definition without any column associated to"
220
            );
221
        }
222
223
        return new IndexDefinition($columns, $unique);
224
    }
225
226
    /**
227
     * Default defined values.
228
     *
229
     * @return array
230
     */
231
    protected function createDefaults(): array
232
    {
233
        //Process defaults
234
        return $this->reflection->getProperty('defaults') ?? [];
235
    }
236
}