Completed
Branch feature/pre-split (0400ca)
by Anton
03:49
created

SchemaBuilder::hasSource()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

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