Completed
Push — master ( 6a1952...4296cb )
by Fabrice
02:35
created

FlowInterruptAbstract::interruptFlow()   B

Complexity

Conditions 5
Paths 10

Size

Total Lines 24
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 18
nc 10
nop 2
dl 0
loc 24
rs 8.5125
c 0
b 0
f 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\Events\FlowEvent;
13
use fab2s\NodalFlow\NodalFlowException;
14
use fab2s\NodalFlow\Nodes\NodeInterface;
15
16
/**
17
 * Abstract Class FlowInterruptAbstract
18
 */
19
abstract class FlowInterruptAbstract extends FlowEventAbstract
20
{
21
    /**
22
     * Continue flag
23
     *
24
     * @var bool
25
     */
26
    protected $continue = false;
27
28
    /**
29
     * Break Flag
30
     *
31
     * @var bool
32
     */
33
    protected $break = false;
34
35
    /**
36
     * @var string|bool
37
     */
38
    protected $interruptNodeId;
39
40
    /**
41
     * @var FlowMapInterface
42
     */
43
    protected $flowMap;
44
45
    /**
46
     * @var FlowRegistryInterface
47
     */
48
    protected $registry;
49
50
    /**
51
     * Current Flow Status
52
     *
53
     * @var FlowStatusInterface
54
     */
55
    protected $flowStatus;
56
57
    /**
58
     * Break the flow's execution, conceptually similar to breaking
59
     * a regular loop
60
     *
61
     * @param InterrupterInterface|null $flowInterrupt
62
     *
63
     * @throws NodalFlowException
64
     *
65
     * @return $this
66
     */
67
    public function breakFlow(InterrupterInterface $flowInterrupt = null)
68
    {
69
        return $this->interruptFlow(InterrupterInterface::TYPE_BREAK, $flowInterrupt);
70
    }
71
72
    /**
73
     * Continue the flow's execution, conceptually similar to continuing
74
     * a regular loop
75
     *
76
     * @param InterrupterInterface|null $flowInterrupt
77
     *
78
     * @throws NodalFlowException
79
     *
80
     * @return $this
81
     */
82
    public function continueFlow(InterrupterInterface $flowInterrupt = null)
83
    {
84
        return $this->interruptFlow(InterrupterInterface::TYPE_CONTINUE, $flowInterrupt);
85
    }
86
87
    /**
88
     * @param string                    $interruptType
89
     * @param InterrupterInterface|null $flowInterrupt
90
     *
91
     * @throws NodalFlowException
92
     *
93
     * @return $this
94
     */
95
    public function interruptFlow($interruptType, InterrupterInterface $flowInterrupt = null)
96
    {
97
        $node  = isset($this->nodes[$this->nodeIdx]) ? $this->nodes[$this->nodeIdx] : null;
98
        switch ($interruptType) {
99
            case InterrupterInterface::TYPE_CONTINUE:
100
                $this->continue = true;
101
                $this->flowMap->incrementFlow('num_continue');
102
                $this->triggerEvent(FlowEvent::FLOW_CONTINUE, $node);
103
                break;
104
            case InterrupterInterface::TYPE_BREAK:
105
                $this->flowStatus = new FlowStatus(FlowStatus::FLOW_DIRTY);
106
                $this->break      = true;
107
                $this->flowMap->incrementFlow('num_break');
108
                $this->triggerEvent(FlowEvent::FLOW_BREAK, $node);
109
                break;
110
            default:
111
                throw new NodalFlowException('FlowInterrupt Type missing');
112
        }
113
114
        if ($flowInterrupt) {
115
            $flowInterrupt->setType($interruptType)->propagate($this);
116
        }
117
118
        return $this;
119
    }
120
121
    /**
122
     * Used to set the eventual Node Target of an Interrupt signal
123
     * set to :
124
     * - A Node Id to target
125
     * - true to interrupt every upstream nodes
126
     *     in this Flow
127
     * - false to only interrupt up to the first
128
     *     upstream Traversable in this Flow
129
     *
130
     * @param null|string|bool $interruptNodeId
131
     *
132
     * @throws NodalFlowException
133
     *
134
     * @return $this
135
     */
136
    public function setInterruptNodeId($interruptNodeId)
137
    {
138
        if ($interruptNodeId !== null && !is_bool($interruptNodeId) && !$this->registry->getNode($interruptNodeId)) {
139
            throw new NodalFlowException('Targeted Node not found in target Flow for Interruption', 1, null, [
140
                'targetFlow' => $this->getId(),
141
                'targetNode' => $interruptNodeId,
142
            ]);
143
        }
144
145
        $this->interruptNodeId = $interruptNodeId;
146
147
        return $this;
148
    }
149
150
    /**
151
     * @param NodeInterface $node
152
     *
153
     * @return bool
154
     */
155
    protected function interruptNode(NodeInterface $node)
156
    {
157
        // if we have an interruptNodeId, bubble up until we match a node
158
        // else stop propagation
159
        return $this->interruptNodeId ? $this->interruptNodeId !== $node->getId() : false;
160
    }
161
}
162