Passed
Push — test ( 847752...4e2470 )
by Tom
02:46
created

FileShower::showServices()   A

Complexity

Conditions 5
Paths 7

Size

Total Lines 33
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 19
CRAP Score 5

Importance

Changes 0
Metric Value
cc 5
eloc 20
nc 7
nop 0
dl 0
loc 33
ccs 19
cts 19
cp 1
crap 5
rs 9.2888
c 0
b 0
f 0
1
<?php
2
3
/* this file is part of pipelines */
4
5
namespace Ktomk\Pipelines\Utility;
6
7
use InvalidArgumentException;
8
use Ktomk\Pipelines\File\Definitions\Service;
9
use Ktomk\Pipelines\File\File;
10
use Ktomk\Pipelines\File\ParseException;
11
use Ktomk\Pipelines\File\Pipeline\Step;
12
use Ktomk\Pipelines\File\Pipeline\Steps;
13
use Ktomk\Pipelines\File\Pipelines;
14
15
/**
16
 * Class FileShower
17
 *
18
 * Shows information about a file
19
 *
20
 * @package Ktomk\Pipelines\Utility
21
 */
22
class FileShower
23
{
24
    /**
25
     * @var callable
26
     */
27
    private $output;
28
29
    /**
30
     * @var File
31
     */
32
    private $file;
33
34
    /**
35
     * FileInfo constructor.
36
     *
37
     * @param callable $output
38
     * @param File $file
39
     */
40 16
    public function __construct($output, File $file)
41
    {
42 16
        $this->output = $output;
43 16
        $this->file = $file;
44 16
    }
45
46
    /**
47
     * @throws InvalidArgumentException
48
     *
49
     * @return int
50
     */
51 2
    public function showImages()
52
    {
53 2
        $images = array();
54
55 2
        foreach ($this->getAllStepsWithServices($this->file) as $step) {
56 2
            $image = $step->getImage();
57 2
            $images[(string)$image] = $image;
58
        }
59
60 2
        foreach ($images as $image) {
61 2
            $this->info($image);
62
        }
63
64 2
        return 0;
65
    }
66
67
    /**
68
     * @return int
69
     */
70 1
    public function showPipelineIds()
71
    {
72 1
        $pipelines = $this->file->getPipelines();
73
74 1
        foreach ($pipelines->getPipelineIds() as $id) {
75 1
            $this->info($id);
76
        }
77
78 1
        return 0;
79
    }
80
81
    /**
82
     * shows pipeline and steps
83
     *
84
     * @return int 0 if there were no errors, 1 if there were errors
85
     */
86 2
    public function showFile()
87
    {
88 2
        $pipelines = $this->file->getPipelines();
89
90 2
        $errors = 0;
91 2
        $table = array(array('PIPELINE ID', 'STEP', 'IMAGE', 'NAME'));
92 2
        foreach ($pipelines->getPipelineIds() as $id) {
93 2
            list($pipeline, $message) = $this->getShowPipeline($pipelines, $id);
94 2
            if ($message) {
95 1
                $table[] = array($id, 'ERROR', $message, '');
96 1
                $errors++;
97
98 1
                continue;
99
            }
100
101 1
            $steps = (null === $pipeline) ? array() : $pipeline->getSteps();
102 1
            foreach ($steps as $index => $step) {
103
                /** @var Step $step */
104 1
                $name = $step->getName();
105 1
                null !== $name && $name = sprintf('"%s"', $name);
106 1
                null === $name && $name = 'no-name';
107 1
                $table[] = array($id, $index + 1, $step->getImage(), $name);
108 1
                foreach ($step->getServices()->getServiceNames() as $serviceName) {
109
                    /** @var Service $service */
110 1
                    ($service = $step->getFile()->getDefinitions()->getServices()->getByName($serviceName)) || $errors++;
111 1
                    $table[] = array($id, $index + 1, $service ? $service->getImage() : 'ERROR', 'service:' . $serviceName);
112
                }
113
            }
114
        }
115
116 2
        $this->textTable($table);
117
118 2
        return $errors ? 1 : 0;
119
    }
120
121
    /**
122
     * shows summary of the file, first pipelines then pipline services
123
     *
124
     * @return int 0 if there were no errors, 1 if there were errors
125
     */
126 5
    public function showPipelines()
127
    {
128 5
        $pipelines = $this->file->getPipelines();
129
130 5
        $errors = 0;
131 5
        $table = array(array('PIPELINE ID', 'IMAGES', 'STEPS'));
132 5
        foreach ($pipelines->getPipelineIds() as $id) {
133 5
            list($pipeline, $message) = $this->getShowPipeline($pipelines, $id);
134 5
            if ($message) {
135 3
                $table[] = array($id, 'ERROR', $message);
136 3
                $errors++;
137
138 3
                continue;
139
            }
140
141 2
            $steps = (null === $pipeline) ? null : $pipeline->getSteps();
142 2
            list($images, $names) = $this->getImagesAndNames($steps);
143
144 2
            $images = $images ? implode(', ', $images) : '';
145 2
            $steps = sprintf('%d%s', count($steps), $names ? ' ("' . implode('"; "', $names) . '")' : '');
146 2
            $table[] = array($id, $images, $steps);
147
        }
148
149 5
        $this->textTable($table);
150
151 5
        return $errors ? 1 : 0;
152
    }
153
154 5
    public function showServices()
155
    {
156 5
        $file = $this->file;
157 5
        $pipelines = $file->getPipelines();
158
159 5
        $errors = 0;
160 5
        $table = array(array('PIPELINE ID', 'STEP', 'SERVICE', 'IMAGE'));
161
162
        try {
163 5
            $serviceDefinitions = $file->getDefinitions()->getServices();
164 2
        } catch (ParseException $e) {
165 2
            $table[] = array('', '', 'ERROR', $e->getParseMessage());
166 2
            $this->textTable($table);
167
168 2
            return 1;
169
        }
170
171 3
        foreach ($pipelines->getPipelineIds() as $id) {
172 3
            list($pipeline, $message) = $this->getShowPipeline($pipelines, $id);
173 3
            if ($message) {
174 1
                $table[] = array($id, '', 'ERROR', $message);
175 1
                $errors++;
176
177 1
                continue;
178
            }
179
180
            list($table, $errors) =
181 2
                $this->tableStepsServices($pipeline->getSteps(), $serviceDefinitions, $id, $table, $errors);
182
        }
183
184 3
        $this->textTable($table);
185
186 3
        return $errors ? 1 : 0;
187
    }
188
189 2
    private function tableStepsServices(Steps $steps, $serviceDefinitions, $id, array $table, $errors)
190
    {
191 2
        foreach ($steps as $step) {
192
            /** @var Step $step */
193 2
            $serviceNames = $step->getServices()->getServiceNames();
194 2
            if (!$serviceNames) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $serviceNames of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
195 1
                continue;
196
            }
197
198 2
            $stepNo = $step->getIndex() + 1;
199
200 2
            foreach ($serviceNames as $name) {
201 2
                if (!$service = $serviceDefinitions->getByName($name)) {
202 1
                    $table[] = array($id, $stepNo, 'ERROR', sprintf('Undefined service: "%s"', $name));
203 1
                    $errors++;
204
                } else {
205 2
                    $table[] = array($id, $stepNo, $name, $service->getImage());
206
                }
207
            }
208
        }
209
210 2
        return array($table, $errors);
211
    }
212
213
    /**
214
     * @param File $file
215
     *
216
     * @return Step[]
217
     */
218 2
    private function getAllSteps(File $file)
219
    {
220 2
        $return = array();
221 2
        foreach ($file->getPipelines()->getPipelines() as $id => $pipeline) {
222 2
            foreach (Steps::fullIter($pipeline->getSteps()) as $index => $step) {
223 2
                $return["${id}:/step/${index}"] = $step;
224
            }
225
        }
226
227 2
        return $return;
228
    }
229
230
    /**
231
     * step iterator w/services
232
     *
233
     * @param File $file
234
     *
235
     * @return Service[]|Step[]
236
     */
237
    private function getAllStepsWithServices(File $file)
238
    {
239 2
        $return = array();
240
241 2
        foreach ($this->getAllSteps($file) as $key => $step) {
242 2
            $return[$key] = $step;
243 2
            foreach ($step->getServices()->getDefinitions() as $name => $service) {
244 1
                $return["${key}/service/${name}"] = $service;
245
            }
246
        }
247
248 2
        return $return;
249
    }
250
251
    /**
252
     * @param Pipelines $pipelines
253
     * @param string $id
254
     *
255
     * @return array
256
     */
257
    private function getShowPipeline(Pipelines $pipelines, $id)
258
    {
259 10
        $pipeline = null;
0 ignored issues
show
Unused Code introduced by
The assignment to $pipeline is dead and can be removed.
Loading history...
260 10
        $message = null;
261
262
        try {
263 10
            $pipeline = $pipelines->getById($id);
264 5
        } catch (ParseException $exception) {
265 4
            $message = $exception->getParseMessage();
266 1
        } catch (InvalidArgumentException $exception) {
267 1
            $message = $exception->getMessage();
268
        }
269
270 10
        return array($pipeline, $message);
271
    }
272
273
    /**
274
     * @param array $table
275
     *
276
     * @return void
277
     */
278
    private function textTable(array $table)
279
    {
280 12
        $sizes = $this->textTableGetSizes($table);
281
282 12
        foreach ($table as $row) {
283 12
            $line = $this->textTableGetRow($row, $sizes);
284 12
            $this->info($line);
285
        }
286 12
    }
287
288
    /**
289
     * @param string $message
290
     *
291
     * @return void
292
     */
293
    private function info($message)
294
    {
295 15
        call_user_func($this->output, $message);
296 15
    }
297
298
    /**
299
     * @param Steps $steps
300
     *
301
     * @return array
302
     */
303
    private function getImagesAndNames(Steps $steps = null)
304
    {
305 2
        $images = array();
306 2
        $names = array();
307
308 2
        foreach (Steps::fullIter($steps) as $step) {
309 2
            $image = $step->getImage()->getName();
310 2
            if (File::DEFAULT_IMAGE !== $image) {
311 2
                $images[] = $image;
312
            }
313 2
            $name = $step->getName();
314 2
            (null !== $name) && $names[] = $name;
315
        }
316
317 2
        $images = array_unique($images);
318
319 2
        return array($images, $names);
320
    }
321
322
    /**
323
     * get max sizes for each column in array table
324
     *
325
     * @param array $table
326
     *
327
     * @return array|int[] sizes
328
     */
329
    private function textTableGetSizes(array $table)
330
    {
331 12
        $sizes = array();
332 12
        foreach ($table[0] as $index => $cell) {
333 12
            $sizes[$index] = 0;
334
        }
335
336 12
        foreach ($table as $row) {
337 12
            foreach ($row as $index => $column) {
338 12
                $sizes[$index] = max($sizes[$index], strlen($column));
339
            }
340
        }
341
342 12
        return $sizes;
343
    }
344
345
    /**
346
     * @param array|string[] $row
347
     * @param array|int[] $sizes
348
     *
349
     * @return string
350
     */
351
    private function textTableGetRow(array $row, array $sizes)
352
    {
353 12
        $line = '';
354 12
        foreach ($row as $index => $column) {
355 12
            $len = strlen($column);
356 12
            $index && $line .= '    ';
357 12
            $line .= $column;
358 12
            $line .= str_repeat(' ', $sizes[$index] - $len);
359
        }
360
361 12
        return $line;
362
    }
363
}
364