Passed
Push — master ( 49fb01...6703f1 )
by Tom
03:03
created

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