Completed
Branch feature/pre-split (ca29cf)
by Anton
03:23
created

ORM::schemaBuilder()   A

Complexity

Conditions 4
Paths 2

Size

Total Lines 19
Code Lines 8

Duplication

Lines 19
Ratio 100 %

Importance

Changes 0
Metric Value
cc 4
eloc 8
nc 2
nop 1
dl 19
loc 19
rs 9.2
c 0
b 0
f 0
1
<?php
2
/**
3
 * components
4
 *
5
 * @author    Wolfy-J
6
 */
7
namespace Spiral\ORM;
8
9
use Spiral\Core\Component;
10
use Spiral\Core\Container\SingletonInterface;
11
use Spiral\Core\FactoryInterface;
12
use Spiral\Core\MemoryInterface;
13
use Spiral\Database\DatabaseManager;
14
use Spiral\Models\ActiveEntityInterface;
15
use Spiral\ORM\Exceptions\ORMException;
16
use Spiral\ORM\Exceptions\SchemaException;
17
use Spiral\ORM\Schemas\SchemaBuilder;
18
use Spiral\ORM\Schemas\SchemaLocator;
19
20
class ORM extends Component implements ORMInterface, SingletonInterface
21
{
22
    /**
23
     * Memory section to store ORM schema.
24
     */
25
    const MEMORY = 'orm.schema';
26
27
    /**
28
     * Already created instantiators.
29
     *
30
     * @invisible
31
     * @var InstantiatorInterface[]
32
     */
33
    private $instantiators = [];
34
35
    /**
36
     * ORM schema.
37
     *
38
     * @invisible
39
     * @var array
40
     */
41
    private $schema = [];
42
43
    /**
44
     * @var DatabaseManager
45
     */
46
    protected $manager;
47
48
    /**
49
     * @var SchemaLocator
50
     */
51
    protected $locator;
52
53
    /**
54
     * @invisible
55
     * @var MemoryInterface
56
     */
57
    protected $memory;
58
59
    /**
60
     * @var FactoryInterface
61
     */
62
    protected $factory;
63
64
    /**
65
     * @param DatabaseManager  $manager
66
     * @param SchemaLocator    $locator
67
     * @param MemoryInterface  $memory
68
     * @param FactoryInterface $factory
69
     */
70 View Code Duplication
    public function __construct(
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
        DatabaseManager $manager,
72
        SchemaLocator $locator,
73
        MemoryInterface $memory,
74
        FactoryInterface $factory
75
    ) {
76
        $this->manager = $manager;
77
        $this->locator = $locator;
78
79
        $this->memory = $memory;
80
        $this->factory = $factory;
81
82
        //Loading schema from memory (if any)
83
        $this->schema = $this->loadSchema();
84
    }
85
86
    /**
87
     * Create instance of ORM SchemaBuilder.
88
     *
89
     * @param bool $locate Set to true to automatically locate available records and record sources
90
     *                     sources in a project files (based on tokenizer scope).
91
     *
92
     * @return SchemaBuilder
93
     *
94
     * @throws SchemaException
95
     */
96 View Code Duplication
    public function schemaBuilder(bool $locate = true): SchemaBuilder
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...
97
    {
98
        /**
99
         * @var SchemaBuilder $builder
100
         */
101
        $builder = $this->factory->make(SchemaBuilder::class, ['manager' => $this->manager]);
102
103
        if ($locate) {
104
            foreach ($this->locator->locateSchemas() as $schema) {
105
                $builder->addSchema($schema);
106
            }
107
108
            foreach ($this->locator->locateSources() as $class => $source) {
109
                $builder->addSource($class, $source);
110
            }
111
        }
112
113
        return $builder;
114
    }
115
116
    /**
117
     * Specify behaviour schema for ORM to be used.
118
     *
119
     * @param SchemaBuilder $builder
120
     * @param bool          $remember Set to true to remember packed schema in memory.
121
     */
122 View Code Duplication
    public function setSchema(SchemaBuilder $builder, bool $remember = 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...
123
    {
124
        $this->schema = $builder->packSchema();
125
126
        if ($remember) {
127
            $this->memory->saveData(static::MEMORY, $this->schema);
128
        }
129
    }
130
131
    /**
132
     * {@inheritdoc}
133
     */
134 View Code Duplication
    public function define(string $class, int $property)
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...
135
    {
136
        if (empty($this->schema)) {
137
            //Update and remember
138
            $this->setSchema($this->schemaBuilder()->renderSchema(), true);
139
        }
140
141
        //Check value
142
        if (!isset($this->schema[$class])) {
143
            throw new ORMException("Undefined ORM schema item '{$class}', make sure schema is updated");
144
        }
145
146
        if (!array_key_exists($property, $this->schema[$class])) {
147
            throw new ORMException("Undefined ORM schema property '{$class}'.'{$property}'");
148
        }
149
150
        return $this->schema[$class][$property];
151
    }
152
153
    //other methods
154
155
    /**
156
     * {@inheritdoc}
157
     */
158
    public function instantiate(
159
        string $class,
160
        $fields = [],
161
        bool $filter = true,
162
        bool $cache = false
163
    ): ActiveEntityInterface {
164
        //todo: cache
165
        return $this->instantiator($class)->instantiate($fields, $filter);
166
    }
167
168
    //todo: __clone
169
170
    /**
171
     * Get object responsible for class instantiation.
172
     *
173
     * @param string $class
174
     *
175
     * @return InstantiatorInterface
176
     */
177 View Code Duplication
    protected function instantiator(string $class): InstantiatorInterface
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...
178
    {
179
        if (isset($this->instantiators[$class])) {
180
            return $this->instantiators[$class];
181
        }
182
183
        //Potential optimization
184
        $instantiator = $this->factory->make(
185
            $this->define($class, self::R_INSTANTIATOR),
186
            [
187
                'class'  => $class,
188
                'orm'    => $this,
189
                'schema' => $this->define($class, self::R_SCHEMA)
190
            ]
191
        );
192
193
        //Constructing instantiator and storing it in cache
194
        return $this->instantiators[$class] = $instantiator;
195
    }
196
197
    /**
198
     * Load packed schema from memory.
199
     *
200
     * @return array
201
     */
202
    protected function loadSchema(): array
203
    {
204
        return (array)$this->memory->loadData(static::MEMORY);
205
    }
206
207
}