Passed
Push — master ( 1522ca...6450ac )
by Anton
04:25
created

Node::getState()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 0
dl 0
loc 7
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * Cycle DataMapper ORM
5
 *
6
 * @license   MIT
7
 * @author    Anton Titov (Wolfy-J)
8
 */
9
10
declare(strict_types=1);
11
12
namespace Cycle\ORM\Heap;
13
14
use Cycle\ORM\Context\ConsumerInterface;
15
use Cycle\ORM\Context\ProducerInterface;
16
use Cycle\ORM\Heap\Traits\RelationTrait;
17
18
/**
19
 * Node (metadata) carries meta information about entity state, changes forwards data to other points through
20
 * inner states.
21
 */
22
final class Node implements ProducerInterface, ConsumerInterface
23
{
24
    use RelationTrait;
25
26
    // Different entity states in a pool
27
    public const PROMISED         = 0;
28
    public const NEW              = 1;
29
    public const MANAGED          = 2;
30
    public const SCHEDULED_INSERT = 3;
31
    public const SCHEDULED_UPDATE = 4;
32
    public const SCHEDULED_DELETE = 5;
33
    public const DELETED          = 6;
34
35
    /** @var string */
36
    private $role;
37
38
    /** @var int */
39
    private $status;
40
41
    /** @var array */
42
    private $data;
43
44
    /** @var null|State */
45
    private $state;
46
47
    /**
48
     * @param int    $status
49
     * @param array  $data
50
     * @param string $role
51
     */
52
    public function __construct(int $status, array $data, string $role)
53
    {
54
        $this->status = $status;
55
        $this->data = $data;
56
        $this->role = $role;
57
    }
58
59
    /**
60
     * Reset state.
61
     */
62
    public function __destruct()
63
    {
64
        $this->data = [];
65
        $this->state = null;
66
        $this->relations = [];
67
    }
68
69
    /**
70
     * @return string
71
     */
72
    public function getRole(): string
73
    {
74
        return $this->role;
75
    }
76
77
    /**
78
     * Current point state (set of changes).
79
     *
80
     * @return State
81
     */
82
    public function getState(): State
83
    {
84
        if ($this->state === null) {
85
            $this->state = new State($this->status, $this->data);
86
        }
87
88
        return $this->state;
89
    }
90
91
    /**
92
     * Set new state value.
93
     *
94
     * @param int $state
95
     */
96
    public function setStatus(int $state): void
97
    {
98
        $this->getState()->setStatus($state);
99
    }
100
101
    /**
102
     * Get current state.
103
     *
104
     * @return int
105
     */
106
    public function getStatus(): int
107
    {
108
        if ($this->state !== null) {
109
            return $this->state->getStatus();
110
        }
111
112
        return $this->status;
113
    }
114
115
    /**
116
     * Set new state data (will trigger state handlers).
117
     *
118
     * @param array $data
119
     */
120
    public function setData(array $data): void
121
    {
122
        $this->getState()->setData($data);
123
    }
124
125
    /**
126
     * Get current state data. Mutalbe inside the transaction.
127
     *
128
     * @return array
129
     */
130
    public function getData(): array
131
    {
132
        if ($this->state !== null) {
133
            return $this->state->getData();
134
        }
135
136
        return $this->data;
137
    }
138
139
    /**
140
     * The intial (post-load) node date. Does not change during the transaction.
141
     *
142
     * @return array
143
     */
144
    public function getInitialData(): array
145
    {
146
        return $this->data;
147
    }
148
149
    /**
150
     * @inheritdoc
151
     */
152
    public function forward(
153
        string $key,
154
        ConsumerInterface $consumer,
155
        string $target,
156
        bool $trigger = false,
157
        int $stream = self::DATA
158
    ): void {
159
        $this->getState()->forward($key, $consumer, $target, $trigger, $stream);
160
    }
161
162
    /**
163
     * @inheritdoc
164
     */
165
    public function register(string $key, $value, bool $fresh = false, int $stream = self::DATA): void
166
    {
167
        $this->getState()->register($key, $value, $fresh, $stream);
168
    }
169
170
    /**
171
     * Sync the point state and return data diff.
172
     *
173
     * @return array
174
     */
175
    public function syncState(): array
176
    {
177
        if ($this->state === null) {
178
            return [];
179
        }
180
181
        $changes = array_udiff_assoc($this->state->getData(), $this->data, [static::class, 'compare']);
182
        foreach ($this->state->getRelations() as $name => $relation) {
183
            $this->setRelation($name, $relation);
184
        }
185
186
        // DELETE handled separately
187
        $this->status = self::MANAGED;
188
        $this->data = $this->state->getData();
189
        $this->state = null;
190
191
        return $changes;
192
    }
193
194
    /**
195
     * Reset point state and flush all the changes.
196
     */
197
    public function resetState(): void
198
    {
199
        $this->state = null;
200
    }
201
202
    /**
203
     * @param mixed $a
204
     * @param mixed $b
205
     * @return int
206
     */
207
    private static function compare($a, $b): int
208
    {
209
        if ($a == $b) {
210
            return 0;
211
        }
212
213
        return ($a > $b) ? 1 : -1;
214
    }
215
}
216