SchemaBuilder   A
last analyzed

Complexity

Total Complexity 22

Size/Duplication

Total Lines 204
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Importance

Changes 0
Metric Value
wmc 22
lcom 1
cbo 5
dl 0
loc 204
rs 10
c 0
b 0
f 0

10 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A addSchema() 0 6 1
A hasSchema() 0 4 1
A getSchema() 0 8 2
A getSchemas() 0 4 1
B addSource() 0 29 6
A hasSource() 0 4 1
A getSource() 0 8 2
B packSchema() 0 26 3
A createIndexes() 0 19 4
1
<?php
2
/**
3
 * Spiral, Core Components
4
 *
5
 * @author Wolfy-J
6
 */
7
8
namespace Spiral\ODM\Schemas;
9
10
use MongoDB\Driver\Exception\RuntimeException as DriverException;
11
use MongoDB\Exception\UnsupportedException;
12
use Spiral\ODM\Exceptions\SchemaException;
13
use Spiral\ODM\MongoManager;
14
use Spiral\ODM\ODMInterface;
15
16
class SchemaBuilder
17
{
18
    /**
19
     * @var MongoManager
20
     */
21
    private $manager;
22
23
    /**
24
     * @var SchemaInterface[]
25
     */
26
    private $schemas = [];
27
28
    /**
29
     * Class names of sources associated with specific class.
30
     *
31
     * @var array
32
     */
33
    private $sources = [];
34
35
    /**
36
     * @param MongoManager $manager
37
     */
38
    public function __construct(MongoManager $manager)
39
    {
40
        $this->manager = $manager;
41
    }
42
43
    /**
44
     * Add new model schema into pool.
45
     *
46
     * @param SchemaInterface $schema
47
     *
48
     * @return self|$this
49
     */
50
    public function addSchema(SchemaInterface $schema): SchemaBuilder
51
    {
52
        $this->schemas[$schema->getClass()] = $schema;
53
54
        return $this;
55
    }
56
57
    /**
58
     * @param string $class
59
     *
60
     * @return bool
61
     */
62
    public function hasSchema(string $class): bool
63
    {
64
        return isset($this->schemas[$class]);
65
    }
66
67
    /**
68
     * @param string $class
69
     *
70
     * @return SchemaInterface
71
     *
72
     * @throws SchemaException
73
     */
74
    public function getSchema(string $class): SchemaInterface
75
    {
76
        if (!$this->hasSchema($class)) {
77
            throw new SchemaException("Unable to find schema for class '{$class}'");
78
        }
79
80
        return $this->schemas[$class];
81
    }
82
83
    /**
84
     * All available document schemas.
85
     *
86
     * @return SchemaInterface[]
87
     */
88
    public function getSchemas(): array
89
    {
90
        return $this->schemas;
91
    }
92
93
    /**
94
     * Associate source class with entity class. Source will be automatically associated with given
95
     * class and all classes from the same collection which extends it.
96
     *
97
     * @param string $class
98
     * @param string $source
99
     *
100
     * @return SchemaBuilder
101
     *
102
     * @throws SchemaException
103
     */
104
    public function addSource(string $class, string $source): SchemaBuilder
105
    {
106
        if (!$this->hasSchema($class)) {
107
            throw new SchemaException("Unable to add source to '{$class}', class is unknown to ODM");
108
        }
109
110
        //See usage below
111
        $scope = [
112
            $this->getSchema($class)->getDatabase(),
113
            $this->getSchema($class)->getCollection()
114
        ];
115
116
        //Ensuring same source for all children classes from same collection
117
        foreach ($this->schemas as $schema) {
118
            if (isset($this->sources[$schema->getClass()])) {
119
                //Already set
120
                continue;
121
            }
122
123
            if (is_a($schema->getClass(), $class, true)) {
124
                //Only for entities from the same collection
125
                if ([$schema->getDatabase(), $schema->getCollection()] == $scope) {
126
                    $this->sources[$schema->getClass()] = $source;
127
                }
128
            }
129
        }
130
131
        return $this;
132
    }
133
134
    /**
135
     * Check if given entity has associated source.
136
     *
137
     * @param string $class
138
     *
139
     * @return bool
140
     */
141
    public function hasSource(string $class): bool
142
    {
143
        return array_key_exists($class, $this->sources);
144
    }
145
146
    /**
147
     * Get source associated with specific class, if any.
148
     *
149
     * @param string $class
150
     *
151
     * @return string|null
152
     */
153
    public function getSource(string $class)
154
    {
155
        if (!$this->hasSource($class)) {
156
            return null;
157
        }
158
159
        return $this->sources[$class];
160
    }
161
162
    /**
163
     * Pack declared schemas in a normalized form.
164
     *
165
     * @return array
166
     */
167
    public function packSchema(): array
168
    {
169
        $result = [];
170
        foreach ($this->schemas as $class => $schema) {
171
            $item = [
172
                //Instantiator class
173
                ODMInterface::D_INSTANTIATOR  => $schema->getInstantiator(),
174
175
                //Primary collection class
176
                ODMInterface::D_PRIMARY_CLASS => $schema->resolvePrimary($this),
177
178
                //Instantiator and entity specific schema
179
                ODMInterface::D_SCHEMA        => $schema->packSchema($this),
180
            ];
181
182
            if (!$schema->isEmbedded()) {
183
                $item[ODMInterface::D_SOURCE_CLASS] = $this->getSource($class);
184
                $item[ODMInterface::D_DATABASE] = $schema->getDatabase();
185
                $item[ODMInterface::D_COLLECTION] = $schema->getCollection();
186
            }
187
188
            $result[$class] = $item;
189
        }
190
191
        return $result;
192
    }
193
194
    /**
195
     * Create all declared indexes.
196
     *
197
     * @throws UnsupportedException
198
     * @throws DriverException
199
     */
200
    public function createIndexes()
201
    {
202
        foreach ($this->schemas as $class => $schema) {
203
            if ($schema->isEmbedded()) {
204
                continue;
205
            }
206
207
            $collection = $this->manager->database(
208
                $schema->getDatabase()
209
            )->selectCollection(
210
                $schema->getCollection()
211
            );
212
213
            //Declaring needed indexes
214
            foreach ($schema->getIndexes() as $index) {
215
                $collection->createIndex($index->getIndex(), $index->getOptions());
216
            }
217
        }
218
    }
219
}