Passed
Push — master ( 1ce7d0...addea1 )
by Tom
02:40
created

ValidationOptions::run()   A

Complexity

Conditions 6
Paths 6

Size

Total Lines 19
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 6

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 6
eloc 11
c 1
b 0
f 1
nc 6
nop 0
dl 0
loc 19
ccs 12
cts 12
cp 1
crap 6
rs 9.2222
1
<?php
2
3
/* this file is part of pipelines */
4
5
namespace Ktomk\Pipelines\Utility;
6
7
use InvalidArgumentException;
8
use JsonSchema\Constraints\Constraint;
9
use JsonSchema\Validator;
10
use Ktomk\Pipelines\Cli\Args;
11
use Ktomk\Pipelines\Cli\Streams;
12
use Ktomk\Pipelines\File\File;
13
use Ktomk\Pipelines\Yaml\Yaml;
14
15
/**
16
 * Class ValidationOptions
17
 *
18
 * validate one or multiple bitbucket-pipelines.yml files against
19
 * the schema
20
 *
21
 * @package Ktomk\Pipelines\Utility
22
 */
23
class ValidationOptions implements Runnable
24
{
25
    /**
26
     * @var Args
27
     */
28
    private $args;
29
30
    /**
31
     * @var callable
32
     */
33
    private $output;
34
35
    /**
36
     * @var File
37
     */
38
    private $file;
39
40
    /**
41
     * bind options
42
     *
43
     * @param Args $args
44
     * @param Streams $streams
45
     * @param File $file
46
     *
47
     * @return ValidationOptions
48
     */
49 1
    public static function bind(Args $args, Streams $streams, File $file)
50
    {
51 1
        return new self($args, $streams, $file);
52
    }
53
54
    /**
55
     * FileOptions constructor.
56
     *
57
     * @param Args $args
58
     * @param callable $output
59
     * @param File $file
60
     */
61 8
    public function __construct(Args $args, $output, File $file)
62
    {
63 8
        $this->args = $args;
64 8
        $this->output = $output;
65 8
        $this->file = $file;
66 8
    }
67
68
    /**
69
     * run options
70
     *
71
     * @throws InvalidArgumentException
72
     * @throws StatusException
73
     * @throws \ReflectionException
74
     *
75
     * @return $this
76
     */
77 6
    public function run()
78
    {
79 6
        $didValidate = false;
80 6
        $allValid = true;
81
82 6
        while ($verify = $this->args->getOptionOptionalArgument('validate', true)) {
83 5
            $didValidate = true;
84 5
            list($isValid) = $this->validate($verify);
85 4
            $isValid || $allValid = false;
86
        };
87
88 5
        if ($didValidate) {
89 4
            throw new StatusException(
90 4
                sprintf('verify done%s', $allValid ? '' : ', with errors'),
91 4
                $allValid ? 0 : 1
92
            );
93
        }
94
95 1
        return $this;
96
    }
97
98
    /**
99
     * @param string|true $verify
100
     *
101
     * @return array
102
     */
103 5
    private function validate($verify)
104
    {
105 5
        if (true === $verify) {
106 1
            $data = $this->file->getArray();
107
        } else {
108 4
            $data = Yaml::file($verify);
109 4
            if (null === $data) {
110 1
                throw new \UnexpectedValueException(sprintf('not a yaml file: %s', $verify));
111
            }
112
        }
113
114 4
        list($isValid, $validator) = $this->validateData($data);
115
116 4
        if (!$isValid) {
117 2
            foreach ($validator->getErrors(Validator::ERROR_DOCUMENT_VALIDATION) as $error) {
118 2
                call_user_func(
119 2
                    $this->output,
120 2
                    sprintf(
121 2
                        '%s[%s] %s',
122 2
                        true === $verify ? '' : sprintf('%s: ', $verify),
123 2
                        $error['property'],
124 2
                        $error['message']
125
                    )
126
                );
127
            }
128
        }
129
130 4
        return array($isValid, $validator);
131
    }
132
133
    /**
134
     * @param array $data
135
     *
136
     * @return array
137
     */
138 4
    private function validateData(array $data)
139
    {
140
        // Validate
141 4
        $validator = new \JsonSchema\Validator();
142 4
        $path = __DIR__ . '/../../lib/pipelines/schema/pipelines-schema.json';
143 4
        if (0 !== strpos($path, 'phar:///', 0)) {
144 4
            $path = 'file://' . $path;
145
        }
146
147 4
        $validator->validate(
148 4
            $data,
149 4
            (object)array('$ref' => $path),
150 4
            Constraint::CHECK_MODE_TYPE_CAST | Constraint::CHECK_MODE_DISABLE_FORMAT
151
        );
152
153 4
        $isValid = $validator->isValid();
154
155 4
        return array($isValid, $validator);
156
    }
157
}
158