Completed
Push — master ( 2efb17...d4d028 )
by Fabrice
02:43
created

FlowInterruptAbstract   A

Complexity

Total Complexity 12

Size/Duplication

Total Lines 138
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
dl 0
loc 138
rs 10
c 0
b 0
f 0
wmc 12

5 Methods

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