Completed
Pull Request — master (#7)
by Fabrice
02:29
created

NodeAbstract::sendTo()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 11
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 6
nc 2
nop 3
1
<?php
2
3
/*
4
 * This file is part of NodalFlow.
5
 *     (c) Fabrice de Stefanis / https://github.com/fab2s/NodalFlow
6
 * This source file is licensed under the MIT license which you will
7
 * find in the LICENSE file or at https://opensource.org/licenses/MIT
8
 */
9
10
namespace fab2s\NodalFlow\Nodes;
11
12
use fab2s\NodalFlow\Flows\FlowIdTrait;
13
use fab2s\NodalFlow\Flows\FlowInterface;
14
use fab2s\NodalFlow\Flows\FlowRegistry;
15
use fab2s\NodalFlow\Flows\FlowRegistryInterface;
16
use fab2s\NodalFlow\NodalFlowException;
17
18
/**
19
 * abstract Class NodeAbstract
20
 */
21
abstract class NodeAbstract implements NodeInterface
22
{
23
    use FlowIdTrait;
24
25
    /**
26
     * The carrying Flow
27
     *
28
     * @var FlowInterface
29
     */
30
    public $carrier;
31
32
    /**
33
     * Indicate if this Node is traversable
34
     *
35
     * @var bool
36
     */
37
    protected $isATraversable;
38
39
    /**
40
     * Indicate if this Node is returning a value
41
     *
42
     * @var bool
43
     */
44
    protected $isAReturningVal;
45
46
    /**
47
     * Indicate if this Node is a Flow (Branch)
48
     *
49
     * @var bool
50
     */
51
    protected $isAFlow;
52
53
    /**
54
     * @var FlowRegistryInterface
55
     */
56
    protected $registry;
57
58
    /**
59
     * @var array
60
     */
61
    protected $nodeIncrements = [];
62
63
    /**
64
     * Instantiate a Node
65
     */
66
    public function __construct()
67
    {
68
        $this->enforceIsATraversable();
69
        $this->registry = new FlowRegistry;
70
    }
71
72
    /**
73
     * Indicate if this Node is Traversable
74
     *
75
     * @return bool
76
     */
77
    public function isTraversable()
78
    {
79
        return (bool) $this->isATraversable;
80
    }
81
82
    /**
83
     * Indicate if this Node is a Flow (Branch)
84
     *
85
     * @return bool true if this node instanceof FlowInterface
86
     */
87
    public function isFlow()
88
    {
89
        return (bool) $this->isAFlow;
90
    }
91
92
    /**
93
     * Indicate if this Node is returning a value
94
     *
95
     * @return bool true if this node is expected to return
96
     *              something to pass on next node as param.
97
     *              If nothing is returned, the previously
98
     *              returned value will be use as param
99
     *              for next nodes.
100
     */
101
    public function isReturningVal()
102
    {
103
        return (bool) $this->isAReturningVal;
104
    }
105
106
    /**
107
     * Set/Reset carrying Flow
108
     *
109
     * @param FlowInterface|null $flow
110
     *
111
     * @return $this
112
     */
113
    public function setCarrier(FlowInterface $flow = null)
114
    {
115
        $this->carrier = $flow;
116
117
        return $this;
118
    }
119
120
    /**
121
     * Get carrying Flow
122
     *
123
     * @return FlowInterface
124
     */
125
    public function getCarrier()
126
    {
127
        return $this->carrier;
128
    }
129
130
    /**
131
     * Get this Node's hash, must be deterministic and unique
132
     *
133
     * @deprecated use `getId` instead
134
     *
135
     * @return string
136
     */
137
    public function getNodeHash()
138
    {
139
        return $this->getId();
140
    }
141
142
    /**
143
     * Get the custom Node increments to be considered during
144
     * Flow execution
145
     * To set additional increment keys, use :
146
     *      'keyName' => int
147
     * to add keyName as increment, starting at int
148
     * or :
149
     *      'keyName' => 'existingIncrement'
150
     * to assign keyName as a reference to an existingIncrement
151
     *
152
     * @return array
153
     */
154
    public function getNodeIncrements()
155
    {
156
        return $this->nodeIncrements;
157
    }
158
159
    /**
160
     * @param string      $flowId
161
     * @param string|null $nodeId
162
     * @param string|null $param
163
     *
164
     * @throws NodalFlowException
165
     *
166
     * @return mixed
167
     */
168
    public function sendTo($flowId, $nodeId = null, $param = null)
169
    {
170
        if (!($flow = $this->registry->getFlow($flowId))) {
171
            throw new NodalFlowException('Cannot sendTo without valid Flow target', 1, null, [
172
                'flowId' => $flowId,
173
                'nodeId' => $nodeId,
174
            ]);
175
        }
176
177
        return $flow->sendTo($nodeId, $param);
178
    }
179
180
    /**
181
     * Make sure this Node is consistent
182
     *
183
     * @throws NodalFlowException
184
     *
185
     * @return $this
186
     */
187
    protected function enforceIsATraversable()
188
    {
189
        if ($this->isFlow()) {
190
            if ($this->isATraversable) {
191
                throw new NodalFlowException('Cannot Traverse a Branch');
192
            }
193
194
            return $this;
195
        }
196
197
        if ($this->isATraversable) {
198
            if (!($this instanceof TraversableNodeInterface)) {
199
                throw new NodalFlowException('Cannot Traverse a Node that does not implement TraversableNodeInterface');
200
            }
201
202
            return $this;
203
        }
204
205
        if (!($this instanceof ExecNodeInterface)) {
206
            throw new NodalFlowException('Cannot Exec a Node that does not implement ExecNodeInterface');
207
        }
208
209
        return $this;
210
    }
211
}
212