Passed
Push — steps ( 2bf0cd...c7b5f4 )
by Tom
04:13
created

Steps::offsetSet()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
nc 1
nop 2
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 1
b 0
f 0
1
<?php
2
3
/* this file is part of pipelines */
4
5
namespace Ktomk\Pipelines\File\Pipeline;
6
7
use Ktomk\Pipelines\File\ParseException;
8
use Ktomk\Pipelines\File\Pipeline;
9
10
/**
11
 * Class Steps
12
 *
13
 * A Pipeline consist of Steps. Some of them can be parallel.
14
 */
15
class Steps implements \ArrayAccess, \Countable, \IteratorAggregate
16
{
17
    /**
18
     * @var Pipeline
19
     */
20
    private $pipeline;
21
22
    /**
23
     * @var array pipeline definition
24
     */
25
    private $array;
26
27
    /**
28
     * @var array|Step[] steps of the pipeline
29
     * @see parseSteps
30
     */
31
    private $steps;
32
33
    /**
34
     * Pipeline constructor.
35
     *
36
     * @param Pipeline $pipeline
37
     * @param array $definition
38
     *
39
     * @throws ParseException
40
     */
41 6
    public function __construct(Pipeline $pipeline, array $definition)
42
    {
43
        // quick validation
44 6
        if (!isset($definition[0])) {
45 1
            ParseException::__('Steps requires a tree of steps');
46
        }
47
48 6
        $this->pipeline = $pipeline;
49 6
        $this->parseSteps($definition);
50 6
    }
51
52
    /**
53
     * @return Pipeline
54
     */
55 1
    public function getPipeline()
56
    {
57 1
        return $this->pipeline;
58
    }
59
60
    /**
61
     * @return array|Step[]
62
     */
63 3
    public function getSteps()
64
    {
65 3
        return $this->steps;
66
    }
67
68
    /**
69
     * Specify data which should be serialized to JSON
70
     *
71
     * @return array
72
     * @since 5.4.0
73
     */
74 1
    public function jsonSerialize()
75
    {
76 1
        $steps = array();
77 1
        foreach ($this->getSteps() as $step) {
78 1
            $steps[] = $step->jsonSerialize();
79
        }
80
81
        return array(
82 1
            'steps' => $steps,
83
        );
84
    }
85
86
    /* @see \ArrayAccess */
87
88 1
    public function offsetExists($offset)
89
    {
90 1
        return isset($this->steps[$offset]);
91
    }
92
93
    /**
94
     * @param mixed $offset
95
     *
96
     * @return Step
97
     */
98 1
    public function offsetGet($offset)
99
    {
100 1
        return $this->steps[$offset];
101
    }
102
103 1
    public function offsetSet($offset, $value)
104
    {
105 1
        throw new \BadMethodCallException('Steps offsets are read-only');
106
    }
107
108 1
    public function offsetUnset($offset)
109
    {
110 1
        throw new \BadMethodCallException('Steps offsets are read-only');
111
    }
112
113
    /* @see \Countable */
114
115 1
    public function count()
116
    {
117 1
        return count($this->steps);
118
    }
119
120
    /* @see \IteratorAggregate */
121
122
    /**
123
     * @return \ArrayIterator|Step[]
124
     */
125 1
    public function getIterator()
126
    {
127 1
        return new \ArrayIterator($this->steps);
128
    }
129
130 6
    private function parseSteps(array $definition)
131
    {
132 6
        $this->array = array();
133 6
        $this->steps = array();
134
135 6
        foreach ($definition as $node) {
136 6
            if (!is_array($node)) {
137 1
                ParseException::__(sprintf('Step expected array, got %s', gettype($node)));
138
            }
139 6
            if (empty($node)) {
140 1
                ParseException::__('Step expected, got empty array');
141
            }
142
143 6
            $keys = array_keys($node);
144 6
            $name = $keys[0];
145 6
            if (!in_array($name, array('step', 'parallel'), true)) {
146 1
                ParseException::__(sprintf('Unknown pipeline step "%s", expected "step" or "parallel"', $name));
147
            }
148
149 6
            $this->node($node, $name);
150
        }
151 6
    }
152
153
    /**
154
     * @param int $index of step, from the zero based index in the list of steps
155
     * @param array $step
156
     * @param array $env [optional] environment variables in array notation for the new step
157
     *
158
     * @return Step
159
     */
160 6
    private function step($index, array $step, array $env = array())
161
    {
162 6
        return new Step($this->pipeline, $index, $step, $env);
163
    }
164
165
    /**
166
     * @param array $node
167
     * @param $name
168
     */
169 6
    private function node(array $node, $name)
170
    {
171 6
        $this->array[] = $node;
172
        switch ($name) {
173 6
            case 'step':
174 6
                $this->steps[] = $this->step(count($this->steps), $node[$name]);
175
176 6
                break;
177 3
            case 'parallel':
178 3
                $this->parallel($node[$name]);
179
180 2
                break;
181
            default:
182
                // @codeCoverageIgnoreStart
183
                throw new \BadMethodCallException(
184
                    sprintf('Unchecked name condition: "%s"', $name)
185
                );
186
            // @codeCoverageIgnoreEnd
187
        }
188 6
    }
189
190
    /**
191
     * @param $node
192
     */
193 3
    private function parallel(array $node)
194
    {
195 3
        $group = array();
196 3
        foreach ($node as $step) {
197 3
            if (!(isset($step['step']) && is_array($step['step']))) {
198 1
                ParseException::__('Parallel step must consist of steps only');
199
            }
200 2
            $group[] = $step['step'];
201
        }
202
203 2
        $total = count($group);
204 2
        foreach ($group as $index => $step) {
205 2
            $this->steps[] = $this->step(
206 2
                count($this->steps),
207 2
                $step,
208
                array(
209 2
                    'BITBUCKET_PARALLEL_STEP' => $index,
210 2
                    'BITBUCKET_PARALLEL_STEP_COUNT' => $total,
211
                )
212
            );
213
        }
214 2
    }
215
}
216