Completed
Branch feature/pre-split (7f7f80)
by Anton
04:48
created

RelationBucket::has()   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
 * components
4
 *
5
 * @author    Wolfy-J
6
 */
7
namespace Spiral\ORM\Entities;
8
9
use Spiral\ORM\CommandInterface;
10
use Spiral\ORM\Commands\CommandQueue;
11
use Spiral\ORM\Exceptions\RelationException;
12
use Spiral\ORM\ORMInterface;
13
use Spiral\ORM\RecordInterface;
14
use Spiral\ORM\RelationInterface;
15
16
/**
17
 * Represent set of entity relations.
18
 */
19
class RelationBucket
20
{
21
    /**
22
     * @var array|RelationInterface[]
23
     */
24
    private $relations = [];
25
26
    /**
27
     * Parent class name.
28
     *
29
     * @var string
30
     */
31
    private $class;
32
33
    /**
34
     * Relations schema.
35
     *
36
     * @var array
37
     */
38
    private $schema = [];
39
40
    /**
41
     * Associates ORM manager.
42
     *
43
     * @var ORMInterface
44
     */
45
    protected $orm;
46
47
    /**
48
     * @param RecordInterface $record
49
     * @param ORMInterface    $orm
50
     */
51
    public function __construct(RecordInterface $record, ORMInterface $orm)
52
    {
53
        $this->class = get_class($record);
54
        $this->schema = $orm->define($this->class, ORMInterface::R_RELATIONS);
0 ignored issues
show
Documentation Bug introduced by
It seems like $orm->define($this->clas...Interface::R_RELATIONS) of type * is incompatible with the declared type array of property $schema.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
55
        $this->orm = $orm;
56
    }
57
58
    /**
59
     * Extract relations data from given entity fields.
60
     *
61
     * @param array $data
62
     */
63
    public function extractRelations(array &$data)
64
    {
65
        //Fetch all relations
66
        $relations = array_intersect_key($data, $this->schema);
67
68
        foreach ($relations as $name => $relation) {
69
            $this->relations[$name] = $relation;
70
            unset($data[$name]);
71
        }
72
    }
73
74
    /**
75
     * Generate command tree with or without relation to parent command in order to specify update
76
     * or insert sequence. Commands might define dependencies between each other in order to extend
77
     * FK values.
78
     *
79
     * @param CommandInterface $parent
80
     *
81
     * @return CommandInterface
82
     */
83
    public function queueRelations(CommandInterface $parent): CommandInterface
84
    {
85
        if (empty($this->relations)) {
86
            //No relations exists, nothing to do
87
            return $parent;
88
        }
89
90
        $queue = new CommandQueue();
91
92
        //Leading relations
93
        foreach ($this->leadingRelations() as $relation) {
94
            //Generating commands needed to save given relation prior to parent command
95
            $queue->addCommand($relation->queueCommands($parent));
0 ignored issues
show
Bug introduced by
The method queueCommands() does not seem to exist on object<Spiral\ORM\RelationInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
96
        }
97
98
        //Parent model save operations
99
        $queue->addCommand($parent);
100
101
        //Depended relations
102
        foreach ($this->dependedRelations() as $relation) {
103
            //Generating commands needed to save relations after parent command being executed
104
            $queue->addCommand($relation->queueCommands($parent));
0 ignored issues
show
Bug introduced by
The method queueCommands() does not seem to exist on object<Spiral\ORM\RelationInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
105
        }
106
107
        return $queue;
108
    }
109
110
    /**
111
     * Check if parent entity has associated relation.
112
     *
113
     * @param string $relation
114
     *
115
     * @return bool
116
     */
117
    public function has(string $relation): bool
118
    {
119
        return isset($this->schema[$relation]);
120
    }
121
122
    /**
123
     * Check if relation has any associated data with it (attention, non loaded relation will be
124
     * automatically pre-loaded).
125
     *
126
     * @param string $relation
127
     *
128
     * @return bool
129
     */
130
    public function hasRelated(string $relation): bool
131
    {
132
        return $this->get($relation)->hasRelated();
0 ignored issues
show
Bug introduced by
The method hasRelated() does not seem to exist on object<Spiral\ORM\RelationInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
133
    }
134
135
    /**
136
     * Data data which is being associated with relation, relation is allowed to return itself if
137
     * needed.
138
     *
139
     * @param string $relation
140
     *
141
     * @return RelationInterface|RecordInterface|mixed
142
     *
143
     * @throws RelationException
144
     */
145
    public function getRelated(string $relation)
146
    {
147
        return $this->get($relation)->getRelated();
0 ignored issues
show
Bug introduced by
The method getRelated() does not seem to exist on object<Spiral\ORM\RelationInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
148
    }
149
150
    /**
151
     * Associated relation with new value (must be compatible with relation format).
152
     *
153
     * @param string $relation
154
     * @param mixed  $value
155
     *
156
     * @throws RelationException
157
     */
158
    public function setRelated(string $relation, $value)
159
    {
160
        if (is_null($value)) {
161
            $this->flushRelated($relation);
162
        }
163
164
        $this->get($relation)->setRelated($value);
0 ignored issues
show
Bug introduced by
The method setRelated() does not seem to exist on object<Spiral\ORM\RelationInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
165
    }
166
167
    /**
168
     * De-associated relation data (idential to assign to null).
169
     *
170
     * @param string $relation
171
     */
172
    public function flushRelated(string $relation)
173
    {
174
        $this->get($relation)->flushRelated();
0 ignored issues
show
Bug introduced by
The method flushRelated() does not seem to exist on object<Spiral\ORM\RelationInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
175
    }
176
177
    /**
178
     * Information about loaded relations.
179
     *
180
     * @return array
181
     */
182
    public function __debugInfo()
183
    {
184
        $relations = [];
185
186
        foreach ($this->schema as $name => $content) {
187
            if (!array_key_exists($name, $this->relations)) {
188
                $relations[$name] = 'none';
189
                continue;
190
            }
191
192
            $relations[$name] = empty($this->relations[$name]) ? 'empty' : 'loaded';
193
        }
194
195
        return $relations;
196
    }
197
198
    /**
199
     * Get associated relation instance.
200
     *
201
     * @param string $relation
202
     *
203
     * @return RelationInterface
204
     */
205
    protected function get(string $relation): RelationInterface
206
    {
207
        if ($this->relations[$relation] instanceof RelationInterface) {
208
            return $this->relations[$relation];
209
        }
210
211
        $instance = $this->orm->makeRelation($this->class, $relation);
212
        if (array_key_exists($relation, $this->relations)) {
213
            //Relation have been pre-loaded (we have related data)
214
            $instance->initData($this->relations[$relation]);
0 ignored issues
show
Bug introduced by
The method initData() does not seem to exist on object<Spiral\ORM\RelationInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
215
        }
216
217
        return $this->relations[$relation] = $instance;
218
    }
219
220
    /**
221
     * list of relations which lead data of parent record (BELONGS_TO).
222
     *
223
     * Example:
224
     *
225
     * $post = new Post();
226
     * $post->user = new User();
227
     *
228
     * @return RelationInterface[]
229
     */
230
    protected function leadingRelations()
231
    {
232
        return [];
233
    }
234
235
    /**
236
     * list of loaded relations which depend on parent record (HAS_MANY, MANY_TO_MANY and etc).
237
     *
238
     * Example:
239
     *
240
     * $post = new Post();
241
     * $post->comments->add(new Comment());
242
     *
243
     * @return RelationInterface[]
244
     */
245
    protected function dependedRelations()
246
    {
247
        return [];
248
    }
249
}