Passed
Push — master ( 71afca...9e5fe0 )
by Tom
04:18
created

Step::getCaches()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2

Importance

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