Passed
Push — test ( ffedf1...feb034 )
by Tom
03:02
created

ValidationOptions   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 136
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 1
Metric Value
eloc 50
dl 0
loc 136
ccs 51
cts 51
cp 1
rs 10
c 1
b 0
f 1
wmc 16

5 Methods

Rating   Name   Duplication   Size   Complexity  
A validateData() 0 18 2
A bind() 0 3 1
B run() 0 24 7
A __construct() 0 5 1
A validate() 0 26 5
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 2
        return $result;
133
    }
134
135
    /**
136
     * @param array $data
137
     *
138
     * @return array
139
     */
140 5
    private function validateData(array $data)
141
    {
142
        // Validate
143 5
        $validator = new \JsonSchema\Validator();
144 5
        $path = __DIR__ . '/../../lib/pipelines/schema/pipelines-schema.json';
145 5
        if (0 !== strpos($path, 'phar:///', 0)) {
146 5
            $path = 'file://' . $path;
147
        }
148
149 5
        $validator->validate(
150 5
            $data,
151 5
            (object)array('$ref' => $path),
152 5
            Constraint::CHECK_MODE_TYPE_CAST | Constraint::CHECK_MODE_DISABLE_FORMAT
153
        );
154
155 5
        $isValid = $validator->isValid();
156
157 5
        return array($isValid, $validator);
158
    }
159
}
160