Completed
Pull Request — master (#13)
by Viacheslav
09:50
created

BuildSchema   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 134
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 81
c 1
b 0
f 0
dl 0
loc 134
rs 10
wmc 14

2 Methods

Rating   Name   Duplication   Size   Complexity  
A setUpDefinition() 0 22 1
C performAction() 0 82 13
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\JsonSchemaFromInstance;
15
use Yaoi\Command;
16
17
class BuildSchema extends Base
18
{
19
    public $schema;
20
    public $data;
21
22
    /** @var string */
23
    public $ptrInSchema;
24
25
    /** @var string */
26
    public $ptrInData;
27
28
    public $jsonl = false;
29
30
    public $useNullable = false;
31
32
    public $useXNullable = false;
33
34
    public $defsPtr = '#/definitions/';
35
36
    /**
37
     * @param Command\Definition $definition
38
     * @param \stdClass|static $options
39
     */
40
    static function setUpDefinition(Command\Definition $definition, $options)
41
    {
42
        $options->data = Command\Option::create()->setIsUnnamed()->setIsRequired()
43
            ->setDescription('Path to data (JSON/YAML)');
44
        $options->schema = Command\Option::create()->setIsUnnamed()
45
            ->setDescription('Path to parent schema');
46
        $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...
47
            ->setDescription('JSON pointer to structure in root schema, default #');
48
        $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...
49
            ->setDescription('JSON pointer to structure in data, default #');
50
        $options->jsonl = Command\Option::create()->setDescription('Data is a stream of JSON Lines');
51
52
        $options->useNullable = Command\Option::create()
53
            ->setDescription('Use `nullable: true` instead of `type: null`, OAS 3.0 compatibility');
54
55
        $options->useXNullable = Command\Option::create()
56
            ->setDescription('Use `x-nullable: true` instead of `type: null`, Swagger 2.0 compatibility');
57
58
        $options->defsPtr = Command\Option::create()->setType()
59
            ->setDescription('Location to put new definitions. default: "#/definitions/"');
60
61
        parent::setUpDefinition($definition, $options);
62
    }
63
64
65
    /**
66
     * @throws ExitCode
67
     * @throws \Swaggest\JsonSchema\Exception
68
     */
69
    public function performAction()
70
    {
71
        if ($this->schema) {
72
            $schemaDataOrig = $this->readData($this->schema);
73
            $schemaData = $schemaDataOrig;
74
75
            $resolver = new ResolverMux();
76
77
            if (!empty($this->ptrInSchema)) {
78
                $baseName = basename($this->schema);
79
                $preloaded = new Preloaded();
80
                $preloaded->setSchemaData($baseName, $schemaData);
81
                $resolver->resolvers[] = $preloaded;
82
                $schemaData = (object)[Schema::PROP_REF => $baseName . $this->ptrInSchema];
83
            }
84
85
            $resolver->resolvers[] = new BasicFetcher();
86
87
            try {
88
                $schema = Schema::import($schemaData, new Context($resolver));
89
            } catch (InvalidValue $e) {
90
                $this->response->error('Invalid schema');
91
                $this->response->addContent($e->getMessage());
92
                throw new ExitCode('', 1);
93
            } catch (\Exception $e) {
94
                $this->response->error('Failed to import schema:' . $e->getMessage());
95
                throw new ExitCode('', 1);
96
            }
97
        } else {
98
            $schema = new Schema();
99
        }
100
101
        $maker = new JsonSchemaFromInstance($schema);
102
        $maker->options->useXNullable = $this->useXNullable;
103
        $maker->options->useNullable = $this->useNullable;
104
        $maker->options->defsPtr = $this->defsPtr;
105
106
        if ($this->jsonl) {
107
            if ($this->ptrInData) {
108
                $pathInData = JsonPointer::splitPath($this->ptrInData);
109
            }
110
111
            $handle = fopen($this->data, "r");
112
            if ($handle) {
0 ignored issues
show
introduced by
$handle is of type false|resource, thus it always evaluated to false.
Loading history...
113
                while (($buffer = fgets($handle)) !== false) {
114
                    $item = json_decode($buffer);
115
                    if ($this->ptrInData) {
116
                        $item = JsonPointer::get($item, $pathInData);
117
                    }
118
                    $maker->addInstanceValue($item);
119
                }
120
                if (!feof($handle)) {
121
                    echo "Error: unexpected fgets() fail\n";
122
                }
123
                fclose($handle);
124
            }
125
        } else {
126
            $data = $this->readData($this->data);
127
            $maker->addInstanceValue($data);
128
        }
129
130
131
        $s = Schema::export($schema);
132
        $this->out = $s;
133
134
        if ($this->ptrInSchema) {
135
            $schemaDataResult = json_decode(json_encode($schemaDataOrig));
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $schemaDataOrig does not seem to be defined for all execution paths leading up to this point.
Loading history...
136
137
            $defs = JsonPointer::get($s, JsonPointer::splitPath(rtrim($this->defsPtr, '/')));
138
            foreach ($defs as $name => $def) {
139
                JsonPointer::add($schemaDataResult, JsonPointer::splitPath($this->defsPtr . $name), $def);
140
            }
141
            JsonPointer::remove($s, JsonPointer::splitPath(rtrim($this->defsPtr, '/')));
142
            JsonPointer::add($schemaDataResult, JsonPointer::splitPath($this->ptrInSchema), $s);
143
144
            $schemaDataResult = json_decode(json_encode($schemaDataResult));
145
            $diff = new JsonDiff($schemaDataOrig, $schemaDataResult, JsonDiff::REARRANGE_ARRAYS);
146
            echo $diff->getDiffCnt();
147
            $this->out = $diff->getRearranged();
148
        }
149
150
        $this->postPerform();
151
    }
152
}