Passed
Push — test ( 0b385b...4e7e0f )
by Tom
02:31
created

Step::getIndex()   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 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
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\Artifacts;
8
use Ktomk\Pipelines\File\Image;
9
use Ktomk\Pipelines\File\ParseException;
10
use Ktomk\Pipelines\File\Pipeline;
11
12
class Step
13
{
14
    /**
15
     * @var array
16
     */
17
    private $step;
18
19
    /**
20
     * @var int number of the step, starting at one
21
     */
22
    private $index;
23
24
    /**
25
     * @var Pipeline
26
     */
27
    private $pipeline;
28
29
    /**
30
     * @var array step environment variables
31
     *   BITBUCKET_PARALLEL_STEP - zero-based index of the current step in the group, e.g. 0, 1, 2, ...
32
     *   BITBUCKET_PARALLEL_STEP_COUNT - total number of steps in the group, e.g. 5.
33
     */
34
    private $env;
35
36
    /**
37
     * Step constructor.
38
     *
39
     * @param Pipeline $pipeline
40
     * @param int $index
41
     * @param array $step
42
     * @param array $env [optional] environment variables in array notation for the new step
43
     */
44 20
    public function __construct(Pipeline $pipeline, $index, array $step, array $env = array())
45
    {
46
        // quick validation: image name
47 20
        Image::validate($step);
48
49
        // quick validation: trigger
50 19
        $this->validateTrigger($step, (bool)$env);
51
52
        // quick validation: script + after-script
53 19
        $this->parseScript($step);
54 16
        $this->parseAfterScript($step);
55
56 16
        $this->pipeline = $pipeline;
57 16
        $this->index = $index;
58 16
        $this->step = $step;
59 16
        $this->env = $env;
60 16
    }
61
62
    /**
63
     * @throws ParseException
64
     *
65
     * @return null|Artifacts
66
     */
67 3
    public function getArtifacts()
68
    {
69 3
        return isset($this->step['artifacts'])
70 1
            ? new Artifacts($this->step['artifacts'])
71 3
            : null;
72
    }
73
74
    /**
75
     * @throws ParseException
76
     *
77
     * @return Image
78
     */
79 3
    public function getImage()
80
    {
81 3
        return isset($this->step['image'])
82 1
            ? new Image($this->step['image'])
83 3
            : $this->pipeline->getFile()->getImage();
84
    }
85
86
    /**
87
     * @return null|string
88
     */
89 3
    public function getName()
90
    {
91 3
        return isset($this->step['name'])
92 1
            ? (string)$this->step['name']
93 3
            : null;
94
    }
95
96
    /**
97
     * @return StepServices
98
     */
99 1
    public function getServices()
100
    {
101 1
        $services = isset($this->step['services']) ? $this->step['services'] : array();
102
103 1
        return new StepServices($this, $services);
104
    }
105
106
    /**
107
     * @return array|string[]
108
     */
109 2
    public function getScript()
110
    {
111 2
        return $this->step['script'];
112
    }
113
114
    /**
115
     * @return array|string[]
116
     */
117 1
    public function getAfterScript()
118
    {
119 1
        if (isset($this->step['after-script'])) {
120 1
            return $this->step['after-script'];
121
        }
122
123 1
        return array();
124
    }
125
126
    /**
127
     * @return bool
128
     */
129 1
    public function isManual()
130
    {
131 1
        if (0 === $this->index) {
132 1
            return false;
133
        }
134
135 1
        return (isset($this->step['trigger']) && 'manual' === $this->step['trigger']);
136
    }
137
138
    /**
139
     * Specify data which should be serialized to JSON
140
     *
141
     * @return array
142
     */
143 1
    public function jsonSerialize()
144
    {
145 1
        $image = $this->getImage();
146 1
        $image = null === $image ? '' : $image->jsonSerialize();
147
148
        return array(
149 1
            'name' => $this->getName(),
150 1
            'image' => $image,
151 1
            'script' => $this->getScript(),
152 1
            'artifacts' => $this->getArtifacts(),
153
        );
154
    }
155
156
    /**
157
     * @return int
158
     */
159 1
    public function getIndex()
160
    {
161 1
        return $this->index;
162
    }
163
164
    /**
165
     * @return Pipeline
166
     * @codeCoverageIgnore
167
     */
168
    public function getPipeline()
169
    {
170
        return $this->pipeline;
171
    }
172
173
    /**
174
     * @return array step container environment variables (e.g. parallel a step)
175
     */
176 1
    public function getEnv()
177
    {
178 1
        return $this->env;
179
    }
180
181
    /**
182
     * @return \Ktomk\Pipelines\File\File
183
     */
184 1
    public function getFile()
185
    {
186 1
        return $this->pipeline->getFile();
187
    }
188
189
    /**
190
     * validate step trigger (none, manual, automatic)
191
     *
192
     * @param array $array
193
     * @param bool $isParallelStep
194
     *
195
     * @return void
196
     */
197 19
    private function validateTrigger(array $array, $isParallelStep)
198
    {
199 19
        if (!array_key_exists('trigger', $array)) {
200 19
            return;
201
        }
202
203 2
        $trigger = $array['trigger'];
204 2
        if ($isParallelStep) {
205 1
            throw new ParseException("Unexpected property 'trigger' in parallel step");
206
        }
207
208 2
        if (!in_array($trigger, array('manual', 'automatic'), true)) {
209 1
            throw new ParseException("'trigger' expects either 'manual' or 'automatic'");
210
        }
211 2
    }
212
213
    /**
214
     * Parse a step script section
215
     *
216
     * @param array $step
217
     *
218
     * @throws ParseException
219
     *
220
     * @return void
221
     */
222 19
    private function parseScript(array $step)
223
    {
224 19
        if (!isset($step['script'])) {
225 1
            throw new ParseException("'step' requires a script");
226
        }
227 18
        $this->parseNamedScript('script', $step);
228 16
    }
229
230
    /**
231
     * @param array $step
232
     *
233
     * @return void
234
     */
235 16
    private function parseAfterScript(array $step)
236
    {
237 16
        if (isset($step['after-script'])) {
238 1
            $this->parseNamedScript('after-script', $step);
239
        }
240 16
    }
241
242
    /**
243
     * @param string $name
244
     * @param $script
245
     *
246
     * @return void
247
     */
248 18
    private function parseNamedScript($name, array $script)
249
    {
250 18
        if (!is_array($script[$name]) || !count($script[$name])) {
251 1
            throw new ParseException("'${name}' requires a list of commands");
252
        }
253
254
        foreach ($script[$name] as $index => $line) {
255
            $this->parseNamedScriptLine($name, $index, $line);
256
        }
257
    }
258
259
    /**
260
     * @param string $name
261
     * @param int $index
262
     * @param null|array|bool|float|int|string $line
263
     *
264
     * @return void
265
     */
266
    private function parseNamedScriptLine($name, $index, $line)
267
    {
268 17
        $standard = is_scalar($line) || null === $line;
269 17
        $pipe = is_array($line) && isset($line['pipe']) && is_string($line['pipe']);
270
271 17
        if (!($standard || ('script' === $name && $pipe))) {
272 1
            throw new ParseException(sprintf(
273 1
                "'%s' requires a list of commands, step #%d is not a command",
274
                $name,
275
                $index
276
            ));
277
        }
278 17
    }
279
}
280