Completed
Branch feature/pre-split (d91fae)
by Anton
05:19
created

ORM::updateSchema()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 22
Code Lines 9

Duplication

Lines 22
Ratio 100 %

Importance

Changes 5
Bugs 0 Features 0
Metric Value
cc 3
eloc 9
nc 4
nop 2
dl 22
loc 22
rs 9.2
c 5
b 0
f 0
1
<?php
2
/**
3
 * Spiral Framework.
4
 *
5
 * @license   MIT
6
 * @author    Anton Titov (Wolfy-J)
7
 */
8
namespace Spiral\ORM;
9
10
use Spiral\Core\Component;
11
use Spiral\Core\Container\SingletonInterface;
12
use Spiral\Models\DataEntity;
13
use Spiral\ORM\Entities\Loader;
14
use Spiral\ORM\Entities\RecordSelector;
15
use Spiral\ORM\Entities\SchemaBuilder;
16
use Spiral\ORM\Entities\Schemas\RecordSchema;
17
use Spiral\ORM\Exceptions\ORMException;
18
use Spiral\Tokenizer\ClassLocatorInterface;
19
20
/**
21
 * ORM component used to manage state of cached Record's schema, record creation and schema
22
 * analysis.
23
 */
24
class ORM extends Component implements SingletonInterface
0 ignored issues
show
Comprehensibility Best Practice introduced by
The type Spiral\ORM\ORM has been defined more than once; this definition is ignored, only the first definition in inprocess/ORM.php (L19-217) is considered.

This check looks for classes that have been defined more than once.

If you can, we would recommend to use standard object-oriented programming techniques. For example, to avoid multiple types, it might make sense to create a common interface, and then multiple, different implementations for that interface.

This also has the side-effect of providing you with better IDE auto-completion, static analysis and also better OPCode caching from PHP.

Loading history...
25
{
26
27
    /**
28
     * Get ORM selector for given class.
29
     *
30
     * @param string $class
31
     * @param Loader $loader
32
     * @return RecordSelector
33
     */
34
    public function selector($class, Loader $loader = null)
35
    {
36
        return new RecordSelector($class, $this, $loader);
37
    }
38
39
    /**
40
     * Get cached schema for specified record by it's name.
41
     *
42
     * @param string $record
43
     * @return array
44
     * @throws ORMException
45
     */
46
    public function schema($record)
47
    {
48
        if (!isset($this->schema[$record])) {
49
            $this->updateSchema();
0 ignored issues
show
Bug introduced by
The method updateSchema() does not exist on Spiral\ORM\ORM. Did you maybe mean schema()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
50
        }
51
52
        if (!isset($this->schema[$record])) {
53
            throw new ORMException("Undefined ORM schema item, unknown record '{$record}'.");
54
        }
55
56
        return $this->schema[$record];
57
    }
58
59
    /**
60
     * Create record relation instance by given relation type, parent and definition (options).
61
     *
62
     * @param int             $type
63
     * @param RecordInterface $parent
64
     * @param array           $definition Relation definition.
65
     * @param array           $data
66
     * @param bool            $loaded
67
     * @return RelationInterface
68
     * @throws ORMException
69
     */
70 View Code Duplication
    public function relation(
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...
71
        $type,
72
        RecordInterface $parent,
73
        $definition,
74
        $data = null,
75
        $loaded = false
76
    ) {
77
        if (!$this->config->hasRelation($type, 'class')) {
78
            throw new ORMException("Undefined relation type '{$type}'.");
79
        }
80
81
        $class = $this->config->relationClass($type, 'class');
82
83
        //For performance reasons class constructed without container
84
        return new $class($this, $parent, $definition, $data, $loaded);
85
    }
86
87
    /**
88
     * Get instance of relation/selection loader based on relation type and definition.
89
     *
90
     * @param int    $type       Relation type.
91
     * @param string $container  Container related to parent loader.
92
     * @param array  $definition Relation definition.
93
     * @param Loader $parent     Parent loader (if presented).
94
     * @return LoaderInterface
95
     * @throws ORMException
96
     */
97 View Code Duplication
    public function loader($type, $container, array $definition, Loader $parent = null)
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...
98
    {
99
        if (!$this->config->hasRelation($type, 'loader')) {
100
            throw new ORMException("Undefined relation loader '{$type}'.");
101
        }
102
103
        $class = $this->config->relationClass($type, 'loader');
104
105
        //For performance reasons class constructed without container
106
        return new $class($this, $container, $definition, $parent);
107
    }
108
109
    /**
110
     * Update ORM records schema, synchronize declared and database schemas and return instance of
111
     * SchemaBuilder.
112
     *
113
     * Attention, syncronize option to be deprecated in a future releases in order to automatically
114
     * generate migrations (Phinx for example) based on declared table difference. See guide.
115
     *
116
     * @param SchemaBuilder $builder    User specified schema builder.
117
     * @param bool          $syncronize Create all required tables and columns
118
     * @return SchemaBuilder
119
     */
120 View Code Duplication
    public function updateSchema(SchemaBuilder $builder = null, $syncronize = false)
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...
121
    {
122
        if (empty($builder)) {
123
            $builder = $this->schemaBuilder();
0 ignored issues
show
Bug introduced by
The method schemaBuilder() does not exist on Spiral\ORM\ORM. Did you maybe mean schema()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
124
        }
125
126
        //Create all required tables and columns
127
        if ($syncronize) {
128
            $builder->synchronizeSchema();
129
        }
130
131
        //Getting normalized (cached) version of schema
132
        $this->schema = $builder->normalizeSchema();
133
134
        //Saving
135
        $this->memory->saveData(static::MEMORY, $this->schema);
136
137
        //Let's reinitialize records
138
        DataEntity::resetInitiated();
139
140
        return $builder;
141
    }
142
143
    /**
144
     * Get instance of ORM SchemaBuilder.
145
     *
146
     * @param ClassLocatorInterface $locator
147
     * @return SchemaBuilder
148
     */
149 View Code Duplication
    public function schemaBuilder(ClassLocatorInterface $locator = null)
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...
150
    {
151
        return $this->factory->make(SchemaBuilder::class, [
152
            'config'  => $this->config,
153
            'orm'     => $this,
154
            'locator' => $locator
155
        ]);
156
    }
157
158
    /**
159
     * Create instance of relation schema based on relation type and given definition (declared in
160
     * record). Resolve using container to support any possible relation type. You can create your
161
     * own relations, loaders and schemas by altering ORM config.
162
     *
163
     * @param mixed         $type
164
     * @param SchemaBuilder $builder
165
     * @param RecordSchema  $record
166
     * @param string        $name
167
     * @param array         $definition
168
     * @return Schemas\RelationInterface
169
     */
170
    public function relationSchema(
171
        $type,
172
        SchemaBuilder $builder,
173
        RecordSchema $record,
174
        $name,
175
        array $definition
176
    ) {
177
        if (!$this->config->hasRelation($type, 'schema')) {
178
            throw new ORMException("Undefined relation schema '{$type}'.");
179
        }
180
181
        //Getting needed relation schema builder
182
        return $this->factory->make(
183
            $this->config->relationClass($type, 'schema'),
184
            compact('builder', 'record', 'name', 'definition')
185
        );
186
    }
187
}
188