Passed
Pull Request — master (#1)
by Fabrice
04:59
created

FlowAbstract   A

Complexity

Total Complexity 21

Size/Duplication

Total Lines 283
Duplicated Lines 0 %

Coupling/Cohesion

Components 4
Dependencies 6

Importance

Changes 0
Metric Value
wmc 21
lcom 4
cbo 6
dl 0
loc 283
rs 10
c 0
b 0
f 0

16 Methods

Rating   Name   Duplication   Size   Complexity  
A getStats() 0 4 1
A getFlowMap() 0 4 1
A getNodes() 0 4 1
A getNodeMap() 0 4 1
A getProgressMod() 0 4 1
A getFlowStatus() 0 4 1
A getFlowId() 0 4 1
A setParent() 0 6 1
A getParent() 0 4 1
A hasParent() 0 4 1
A setProgressMod() 0 6 1
B interruptFlow() 0 22 4
A setInterruptNodeId() 0 6 1
A setCallBack() 0 6 1
A interruptNode() 0 6 2
A triggerCallback() 0 8 2
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
     * The current registered Callback class if any
51
     *
52
     * @var CallbackInterface|null
53
     */
54
    protected $callBack;
55
56
    /**
57
     * Continue flag
58
     *
59
     * @var bool
60
     */
61
    protected $continue = false;
62
63
    /**
64
     * Break Flag
65
     *
66
     * @var bool
67
     */
68
    protected $break = false;
69
70
    /**
71
     * Progress modulo to apply
72
     * Set to x if you want to trigger
73
     * progress every x iterations in flow
74
     *
75
     * @var int
76
     */
77
    protected $progressMod = 1024;
78
79
    /**
80
     * @var string|bool
81
     */
82
    protected $interruptNodeId;
83
84
    /**
85
     * Get the stats array with latest Node stats
86
     *
87
     * @return array
88
     */
89
    public function getStats()
90
    {
91
        return $this->flowMap->getStats();
92
    }
93
94
    /**
95
     * Get the stats array with latest Node stats
96
     *
97
     * @return FlowMapInterface
98
     */
99
    public function getFlowMap()
100
    {
101
        return $this->flowMap;
102
    }
103
104
    /**
105
     * Get the Node array
106
     *
107
     * @return NodeInterface[]
108
     */
109
    public function getNodes()
110
    {
111
        return $this->nodes;
112
    }
113
114
    /**
115
     * Get/Generate Node Map
116
     *
117
     * @return array
118
     */
119
    public function getNodeMap()
120
    {
121
        return $this->flowMap->getNodeMap();
122
    }
123
124
    /**
125
     * Get current $progressMod
126
     *
127
     * @return int
128
     */
129
    public function getProgressMod()
130
    {
131
        return $this->progressMod;
132
    }
133
134
    /**
135
     * The Flow status can either indicate be:
136
     *      - clean (isClean()): everything went well
137
     *      - dirty (isDirty()): one Node broke the flow
138
     *      - exception (isException()): an exception was raised during the flow
139
     *
140
     * @return FlowStatusInterface
141
     */
142
    public function getFlowStatus()
143
    {
144
        return $this->flowStatus;
145
    }
146
147
    /**
148
     * getId() alias for backward compatibility
149
     *
150
     * @deprecated use `getId` instead
151
     *
152
     * @return string
153
     */
154
    public function getFlowId()
155
    {
156
        return $this->getId();
157
    }
158
159
    /**
160
     * Set parent Flow, happens only when branched
161
     *
162
     * @param FlowInterface $flow
163
     *
164
     * @return $this
165
     */
166
    public function setParent(FlowInterface $flow)
167
    {
168
        $this->parent = $flow;
169
170
        return $this;
171
    }
172
173
    /**
174
     * Get eventual parent Flow
175
     *
176
     * @return FlowInterface
177
     */
178
    public function getParent()
179
    {
180
        return $this->parent;
181
    }
182
183
    /**
184
     * Tells if this flow has a parent
185
     *
186
     * @return bool
187
     */
188
    public function hasParent()
189
    {
190
        return !empty($this->parent);
191
    }
192
193
    /**
194
     * Define the progress modulo, Progress Callback will be
195
     * triggered upon each iteration in the flow modulo $progressMod
196
     *
197
     * @param int $progressMod
198
     *
199
     * @return $this
200
     */
201
    public function setProgressMod($progressMod)
202
    {
203
        $this->progressMod = max(1, (int) $progressMod);
204
205
        return $this;
206
    }
207
208
    /**
209
     * @param string                    $interruptType
210
     * @param InterrupterInterface|null $flowInterrupt
211
     *
212
     * @throws NodalFlowException
213
     *
214
     * @return $this
215
     */
216
    public function interruptFlow($interruptType, InterrupterInterface $flowInterrupt = null)
217
    {
218
        switch ($interruptType) {
219
            case InterrupterInterface::TYPE_CONTINUE:
220
                $this->continue = true;
221
                $this->flowMap->incrementFlow('num_continue');
222
                break;
223
            case InterrupterInterface::TYPE_BREAK:
224
                $this->flowStatus = new FlowStatus(FlowStatus::FLOW_DIRTY);
225
                $this->break      = true;
226
                $this->flowMap->incrementFlow('num_break');
227
                break;
228
            default:
229
                throw new NodalFlowException('FlowInterrupt Type missing');
230
        }
231
232
        if ($flowInterrupt) {
233
            $flowInterrupt->setType($interruptType)->propagate($this);
234
        }
235
236
        return $this;
237
    }
238
239
    /**
240
     * Used to set the eventual Node Target of an Interrupt signal
241
     * set to :
242
     * - A node hash to target
243
     * - true to interrupt every upstream nodes
244
     *     in this Flow
245
     * - false to only interrupt up to the first
246
     *     upstream Traversable in this Flow
247
     *
248
     * @param string|bool $interruptNodeId
249
     *
250
     * @return $this
251
     */
252
    public function setInterruptNodeId($interruptNodeId)
253
    {
254
        $this->interruptNodeId = $interruptNodeId;
255
256
        return $this;
257
    }
258
259
    /**
260
     * Register callback class
261
     *
262
     * @param CallbackInterface $callBack
263
     *
264
     * @return $this
265
     */
266
    public function setCallBack(CallbackInterface $callBack)
267
    {
268
        $this->callBack = $callBack;
269
270
        return $this;
271
    }
272
273
    /**
274
     * @param NodeInterface $node
275
     *
276
     * @return bool
277
     */
278
    protected function interruptNode(NodeInterface $node)
279
    {
280
        // if we have an interruptNodeId, bubble up until we match a node
281
        // else stop propagation
282
        return $this->interruptNodeId ? $this->interruptNodeId !== $node->getId() : false;
283
    }
284
285
    /**
286
     * KISS helper to trigger Callback slots
287
     *
288
     * @param string             $which
289
     * @param null|NodeInterface $node
290
     *
291
     * @return $this
292
     */
293
    protected function triggerCallback($which, NodeInterface $node = null)
294
    {
295
        if (null !== $this->callBack) {
296
            $this->callBack->$which($this, $node);
297
        }
298
299
        return $this;
300
    }
301
}
302