Passed
Push — master ( 2c1ebd...f7ac7b )
by Viacheslav
10:50 queued 53s
created

BuildSchema::performAction()   F

Complexity

Conditions 19
Paths 164

Size

Total Lines 101
Code Lines 68

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 19
eloc 68
c 1
b 0
f 0
nc 164
nop 0
dl 0
loc 101
rs 3.9833

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
4
namespace Swaggest\JsonCli;
5
6
use Swaggest\JsonCli\JsonSchema\ResolverMux;
7
use Swaggest\JsonDiff\JsonDiff;
8
use Swaggest\JsonDiff\JsonPointer;
9
use Swaggest\JsonSchema\Context;
10
use Swaggest\JsonSchema\InvalidValue;
11
use Swaggest\JsonSchema\RemoteRef\BasicFetcher;
12
use Swaggest\JsonSchema\RemoteRef\Preloaded;
13
use Swaggest\JsonSchema\Schema;
14
use Swaggest\JsonSchemaMaker\SchemaMaker;
15
use Yaoi\Command;
16
17
class BuildSchema extends Base
18
{
19
    public $schema;
20
    public $data;
21
22
    public $additionalData;
23
24
    /** @var string */
25
    public $ptrInSchema;
26
27
    /** @var string */
28
    public $ptrInData;
29
30
    public $jsonl = false;
31
32
    public $useNullable = false;
33
34
    public $useXNullable = false;
35
36
    public $collectExamples = false;
37
38
    public $defsPtr = '#/definitions/';
39
40
    /**
41
     * @param Command\Definition $definition
42
     * @param \stdClass|static $options
43
     */
44
    static function setUpDefinition(Command\Definition $definition, $options)
45
    {
46
        $options->data = Command\Option::create()->setIsUnnamed()->setIsRequired()
47
            ->setDescription('Path to data (JSON/YAML)');
48
        $options->schema = Command\Option::create()->setIsUnnamed()
49
            ->setDescription('Path to parent schema');
50
        $options->ptrInSchema = Command\Option::create()->setType()
0 ignored issues
show
Documentation Bug introduced by
It seems like Yaoi\Command\Option::cre...oot schema, default #') of type Yaoi\Command\Option is incompatible with the declared type string of property $ptrInSchema.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
51
            ->setDescription('JSON pointer to structure in root schema, default #');
52
        $options->ptrInData = Command\Option::create()->setType()
0 ignored issues
show
Documentation Bug introduced by
It seems like Yaoi\Command\Option::cre...re in data, default #') of type Yaoi\Command\Option is incompatible with the declared type string of property $ptrInData.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
53
            ->setDescription('JSON pointer to structure in data, default #');
54
        $options->jsonl = Command\Option::create()->setDescription('Data is a stream of JSON Lines');
55
56
        $options->useNullable = Command\Option::create()
57
            ->setDescription('Use `nullable: true` instead of `type: null`, OAS 3.0 compatibility');
58
59
        $options->useXNullable = Command\Option::create()
60
            ->setDescription('Use `x-nullable: true` instead of `type: null`, Swagger 2.0 compatibility');
61
62
        $options->defsPtr = Command\Option::create()->setType()
63
            ->setDescription('Location to put new definitions. default: "#/definitions/"');
64
65
        $options->collectExamples = Command\Option::create()
66
            ->setDescription('Collect scalar values example');
67
68
        $options->additionalData = Command\Option::create()->setType()->setIsVariadic()
69
            ->setDescription('Additional paths to data');
70
71
        parent::setUpDefinition($definition, $options);
72
    }
73
74
75
    /**
76
     * @throws ExitCode
77
     * @throws \Swaggest\JsonSchema\Exception
78
     */
79
    public function performAction()
80
    {
81
        $schema = new Schema();
82
83
        if ($this->schema) {
84
            $schemaDataOrig = $this->readData($this->schema);
85
            $schemaData = $schemaDataOrig;
86
87
            $resolver = new ResolverMux();
88
89
            if (!empty($this->ptrInSchema)) {
90
                $baseName = basename($this->schema);
91
                $preloaded = new Preloaded();
92
                $preloaded->setSchemaData($baseName, $schemaData);
93
                $resolver->resolvers[] = $preloaded;
94
                $schemaData = (object)[Schema::PROP_REF => $baseName . $this->ptrInSchema];
95
            }
96
97
            $resolver->resolvers[] = new BasicFetcher();
98
99
            try {
100
                $schemaContract = Schema::import($schemaData, new Context($resolver));
101
                if ($schemaContract instanceof Schema) {
102
                    $schema = $schemaContract;
103
                }
104
            } catch (InvalidValue $e) {
105
                $this->response->error('Invalid schema');
106
                $this->response->addContent($e->getMessage());
107
                throw new ExitCode('', 1);
108
            } catch (\Exception $e) {
109
                $this->response->error('Failed to import schema:' . $e->getMessage());
110
                throw new ExitCode('', 1);
111
            }
112
        }
113
114
        $maker = new SchemaMaker($schema);
115
        $maker->options->useXNullable = $this->useXNullable;
116
        $maker->options->useNullable = $this->useNullable;
117
        $maker->options->defsPtr = $this->defsPtr;
118
        $maker->options->collectExamples = $this->collectExamples;
119
120
        if ($this->jsonl) {
121
            $pathInData = [];
122
            if ($this->ptrInData) {
123
                $pathInData = JsonPointer::splitPath($this->ptrInData);
124
            }
125
126
            $handle = fopen($this->data, "r");
127
            if ($handle) {
0 ignored issues
show
introduced by
$handle is of type false|resource, thus it always evaluated to false.
Loading history...
128
                while (($buffer = fgets($handle)) !== false) {
129
                    $item = json_decode($buffer);
130
                    if ($this->ptrInData) {
131
                        $item = JsonPointer::get($item, $pathInData);
132
                    }
133
                    $maker->addInstanceValue($item);
134
                }
135
                if (!feof($handle)) {
136
                    echo "Error: unexpected fgets() fail\n";
137
                }
138
                fclose($handle);
139
            }
140
        } else {
141
            $data = $this->readData($this->data);
142
            $maker->addInstanceValue($data);
143
144
            if (!empty($this->additionalData)) {
145
                foreach ($this->additionalData as $path) {
146
                    $data = $this->readData($path);
147
                    $maker->addInstanceValue($data);
148
                }
149
            }
150
        }
151
152
153
        $s = Schema::export($schema);
154
        $this->out = $s;
155
156
        if ($this->ptrInSchema && isset($schemaDataOrig)) {
157
            $tmp = json_encode($schemaDataOrig);
158
            if ($tmp === false) {
159
                throw new ExitCode('Failed to encode JSON', 1);
160
            }
161
            $schemaDataResult = json_decode($tmp);
162
163
            $defs = JsonPointer::get($s, JsonPointer::splitPath(rtrim($this->defsPtr, '/')));
164
            foreach ($defs as $name => $def) {
165
                JsonPointer::add($schemaDataResult, JsonPointer::splitPath($this->defsPtr . $name), $def);
166
            }
167
            JsonPointer::remove($s, JsonPointer::splitPath(rtrim($this->defsPtr, '/')));
168
            JsonPointer::add($schemaDataResult, JsonPointer::splitPath($this->ptrInSchema), $s);
169
170
            $tmp = json_encode($schemaDataResult);
171
            if ($tmp === false) {
172
                throw new ExitCode('Failed to encode JSON', 1);
173
            }
174
            $schemaDataResult = json_decode($tmp);
175
            $diff = new JsonDiff($schemaDataOrig, $schemaDataResult, JsonDiff::REARRANGE_ARRAYS);
176
            $this->out = $diff->getRearranged();
177
        }
178
179
        $this->postPerform();
180
    }
181
}