Passed
Push — master ( 2f2d63...13c5ea )
by Fabrice
02:00
created

FlowAbstract::hasParent()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
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\Flows;
11
12
use fab2s\NodalFlow\Callbacks\CallbackInterface;
13
use fab2s\NodalFlow\NodalFlowException;
14
use fab2s\NodalFlow\Nodes\NodeInterface;
15
16
/**
17
 * Abstract Class FlowAbstract
18
 */
19
abstract class FlowAbstract implements FlowInterface
20
{
21
    use FlowIdTrait;
22
23
    /**
24
     * The parent Flow, only set when branched
25
     *
26
     * @var FlowInterface
27
     */
28
    public $parent;
29
30
    /**
31
     * Current Flow Status
32
     *
33
     * @var FlowStatusInterface
34
     */
35
    protected $flowStatus;
36
37
    /**
38
     * The underlying node structure
39
     *
40
     * @var NodeInterface[]
41
     */
42
    protected $nodes = [];
43
44
    /**
45
     * @var FlowMapInterface
46
     */
47
    protected $flowMap;
48
49
    /**
50
     * @var FlowRegistryInterface
51
     */
52
    protected $registry;
53
54
    /**
55
     * The current registered Callback class if any
56
     *
57
     * @var CallbackInterface|null
58
     */
59
    protected $callBack;
60
61
    /**
62
     * Continue flag
63
     *
64
     * @var bool
65
     */
66
    protected $continue = false;
67
68
    /**
69
     * Break Flag
70
     *
71
     * @var bool
72
     */
73
    protected $break = false;
74
75
    /**
76
     * Progress modulo to apply
77
     * Set to x if you want to trigger
78
     * progress every x iterations in flow
79
     *
80
     * @var int
81
     */
82
    protected $progressMod = 1024;
83
84
    /**
85
     * @var string|bool
86
     */
87
    protected $interruptNodeId;
88
89
    /**
90
     * Get the stats array with latest Node stats
91
     *
92
     * @return array
93
     */
94
    public function getStats()
95
    {
96
        return $this->flowMap->getStats();
97
    }
98
99
    /**
100
     * Get the stats array with latest Node stats
101
     *
102
     * @return FlowMapInterface
103
     */
104
    public function getFlowMap()
105
    {
106
        return $this->flowMap;
107
    }
108
109
    /**
110
     * Get the Node array
111
     *
112
     * @return NodeInterface[]
113
     */
114
    public function getNodes()
115
    {
116
        return $this->nodes;
117
    }
118
119
    /**
120
     * Get/Generate Node Map
121
     *
122
     * @return array
123
     */
124
    public function getNodeMap()
125
    {
126
        return $this->flowMap->getNodeMap();
127
    }
128
129
    /**
130
     * Get current $progressMod
131
     *
132
     * @return int
133
     */
134
    public function getProgressMod()
135
    {
136
        return $this->progressMod;
137
    }
138
139
    /**
140
     * The Flow status can either indicate be:
141
     *      - clean (isClean()): everything went well
142
     *      - dirty (isDirty()): one Node broke the flow
143
     *      - exception (isException()): an exception was raised during the flow
144
     *
145
     * @return FlowStatusInterface
146
     */
147
    public function getFlowStatus()
148
    {
149
        return $this->flowStatus;
150
    }
151
152
    /**
153
     * getId() alias for backward compatibility
154
     *
155
     * @deprecated use `getId` instead
156
     *
157
     * @return string
158
     */
159
    public function getFlowId()
160
    {
161
        return $this->getId();
162
    }
163
164
    /**
165
     * Set parent Flow, happens only when branched
166
     *
167
     * @param FlowInterface $flow
168
     *
169
     * @return $this
170
     */
171
    public function setParent(FlowInterface $flow)
172
    {
173
        $this->parent = $flow;
174
175
        return $this;
176
    }
177
178
    /**
179
     * Get eventual parent Flow
180
     *
181
     * @return FlowInterface
182
     */
183
    public function getParent()
184
    {
185
        return $this->parent;
186
    }
187
188
    /**
189
     * Tells if this flow has a parent
190
     *
191
     * @return bool
192
     */
193
    public function hasParent()
194
    {
195
        return !empty($this->parent);
196
    }
197
198
    /**
199
     * Define the progress modulo, Progress Callback will be
200
     * triggered upon each iteration in the flow modulo $progressMod
201
     *
202
     * @param int $progressMod
203
     *
204
     * @return $this
205
     */
206
    public function setProgressMod($progressMod)
207
    {
208
        $this->progressMod = max(1, (int) $progressMod);
209
210
        return $this;
211
    }
212
213
    /**
214
     * @param string                    $interruptType
215
     * @param InterrupterInterface|null $flowInterrupt
216
     *
217
     * @throws NodalFlowException
218
     *
219
     * @return $this
220
     */
221
    public function interruptFlow($interruptType, InterrupterInterface $flowInterrupt = null)
222
    {
223
        switch ($interruptType) {
224
            case InterrupterInterface::TYPE_CONTINUE:
225
                $this->continue = true;
226
                $this->flowMap->incrementFlow('num_continue');
227
                break;
228
            case InterrupterInterface::TYPE_BREAK:
229
                $this->flowStatus = new FlowStatus(FlowStatus::FLOW_DIRTY);
230
                $this->break      = true;
231
                $this->flowMap->incrementFlow('num_break');
232
                break;
233
            default:
234
                throw new NodalFlowException('FlowInterrupt Type missing');
235
        }
236
237
        if ($flowInterrupt) {
238
            $flowInterrupt->setType($interruptType)->propagate($this);
239
        }
240
241
        return $this;
242
    }
243
244
    /**
245
     * Used to set the eventual Node Target of an Interrupt signal
246
     * set to :
247
     * - A node hash to target
248
     * - true to interrupt every upstream nodes
249
     *     in this Flow
250
     * - false to only interrupt up to the first
251
     *     upstream Traversable in this Flow
252
     *
253
     * @param string|bool $interruptNodeId
254
     *
255
     * @return $this
256
     */
257
    public function setInterruptNodeId($interruptNodeId)
258
    {
259
        $this->interruptNodeId = $interruptNodeId;
260
261
        return $this;
262
    }
263
264
    /**
265
     * Register callback class
266
     *
267
     * @param CallbackInterface $callBack
268
     *
269
     * @return $this
270
     */
271
    public function setCallBack(CallbackInterface $callBack)
272
    {
273
        $this->callBack = $callBack;
274
275
        return $this;
276
    }
277
278
    /**
279
     * Get this Flow's root Flow
280
     *
281
     * @param FlowInterface $flow Root Flow, or self if root flow
282
     *
283
     * @return FlowInterface
284
     */
285
    public function getRootFlow(FlowInterface $flow)
286
    {
287
        while ($flow->hasParent()) {
288
            $flow = $flow->getParent();
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $flow. This often makes code more readable.
Loading history...
289
        }
290
291
        return $flow;
292
    }
293
294
    /**
295
     * @param NodeInterface $node
296
     *
297
     * @return bool
298
     */
299
    protected function interruptNode(NodeInterface $node)
300
    {
301
        // if we have an interruptNodeId, bubble up until we match a node
302
        // else stop propagation
303
        return $this->interruptNodeId ? $this->interruptNodeId !== $node->getId() : false;
304
    }
305
306
    /**
307
     * KISS helper to trigger Callback slots
308
     *
309
     * @param string             $which
310
     * @param null|NodeInterface $node
311
     *
312
     * @return $this
313
     */
314
    protected function triggerCallback($which, NodeInterface $node = null)
315
    {
316
        if (null !== $this->callBack) {
317
            $this->callBack->$which($this, $node);
318
        }
319
320
        return $this;
321
    }
322
}
323