Completed
Pull Request — master (#5)
by Viacheslav
07:00
created

GenPhp::setUpDefinition()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 27
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 19
c 1
b 0
f 0
nc 1
nop 2
dl 0
loc 27
rs 9.6333
1
<?php
2
3
namespace Swaggest\JsonCli;
4
5
use Swaggest\JsonSchema\Context;
6
use Swaggest\JsonSchema\RemoteRef\Preloaded;
7
use Swaggest\JsonSchema\Schema;
8
use Swaggest\PhpCodeBuilder\App\PhpApp;
9
use Swaggest\PhpCodeBuilder\JsonSchema\ClassHookCallback;
10
use Swaggest\PhpCodeBuilder\JsonSchema\PhpBuilder;
11
use Swaggest\PhpCodeBuilder\PhpClass;
12
use Swaggest\PhpCodeBuilder\PhpCode;
13
use Yaoi\Command;
14
15
class GenPhp extends Command
16
{
17
    /** @var string */
18
    public $schema;
19
    /** @var string */
20
    public $ns;
21
    /** @var string */
22
    public $nsPath;
23
    /** @var string */
24
    public $rootName = 'Structure';
25
    /** @var string[] */
26
    public $defPtr = ['#/definitions'];
27
    /** @var string[] */
28
    public $ptrInSchema;
29
30
    /** @var bool */
31
    public $setters = false;
32
    /** @var bool */
33
    public $getters = false;
34
    /** @var bool */
35
    public $noEnumConst = false;
36
37
    /**
38
     * @param Command\Definition $definition
39
     * @param \stdClass|static $options
40
     */
41
    public static function setUpDefinition(Command\Definition $definition, $options)
42
    {
43
        $definition->description = 'Generate PHP code from JSON schema';
44
        $options->schema = Command\Option::create()
0 ignored issues
show
Documentation Bug introduced by
It seems like Yaoi\Command\Option::cre...amed()->setIsRequired() of type Yaoi\Command\Option is incompatible with the declared type string of property $schema.

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...
45
            ->setDescription('Path to JSON schema file')->setIsUnnamed()->setIsRequired();
46
47
        $options->ns = Command\Option::create()
0 ignored issues
show
Documentation Bug introduced by
It seems like Yaoi\Command\Option::cre...Type()->setIsRequired() of type Yaoi\Command\Option is incompatible with the declared type string of property $ns.

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...
48
            ->setDescription('Namespace to use for generated classes, example \MyClasses')->setType()->setIsRequired();
49
50
        $options->nsPath = Command\Option::create()
0 ignored issues
show
Documentation Bug introduced by
It seems like Yaoi\Command\Option::cre...Type()->setIsRequired() of type Yaoi\Command\Option is incompatible with the declared type string of property $nsPath.

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('Path to store generated classes, example ./src/MyClasses')
52
            ->setType()
53
            ->setIsRequired();
54
55
        $options->ptrInSchema = Command\Option::create()->setType()->setIsVariadic()
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...
56
            ->setDescription('JSON pointers to structure in in root schema, default #');
57
58
        $options->rootName = Command\Option::create()->setType()
0 ignored issues
show
Documentation Bug introduced by
It seems like Yaoi\Command\Option::cre...ly used for # pointer') of type Yaoi\Command\Option is incompatible with the declared type string of property $rootName.

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...
59
            ->setDescription('Go root struct name, default "Structure", only used for # pointer');
60
61
        $options->defPtr = Command\Option::create()->setType()->setIsVariadic()
0 ignored issues
show
Documentation Bug introduced by
It seems like Yaoi\Command\Option::cre...default #/definitions') of type Yaoi\Command\Option is incompatible with the declared type string[] of property $defPtr.

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...
62
            ->setDescription('Definitions pointers to strip from symbol names, default #/definitions');
63
64
        $options->setters = Command\Option::create()->setDescription('Build setters');
0 ignored issues
show
Documentation Bug introduced by
It seems like Yaoi\Command\Option::cre...iption('Build setters') of type Yaoi\Command\Option is incompatible with the declared type boolean of property $setters.

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...
65
        $options->getters = Command\Option::create()->setDescription('Build getters');
0 ignored issues
show
Documentation Bug introduced by
It seems like Yaoi\Command\Option::cre...iption('Build getters') of type Yaoi\Command\Option is incompatible with the declared type boolean of property $getters.

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...
66
        $options->noEnumConst = Command\Option::create()
0 ignored issues
show
Documentation Bug introduced by
It seems like Yaoi\Command\Option::cre...for enum/const values') of type Yaoi\Command\Option is incompatible with the declared type boolean of property $noEnumConst.

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...
67
            ->setDescription('Do not create constants for enum/const values');
68
69
    }
70
71
72
    public function performAction()
73
    {
74
        $dataValue = Base::readJsonOrYaml($this->schema, $this->response);
75
        if (!$dataValue) {
76
            $this->response->error('Unable to find schema in ' . $this->schema);
77
            die(1);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
78
        }
79
80
        $baseName = null;
81
        $skipRoot = false;
82
        if (empty($this->ptrInSchema)) {
83
            $preloaded = new Preloaded();
84
            $schema = Schema::import($dataValue, new Context($preloaded));
85
        } else {
86
            $baseName = basename($this->schema);
87
            $skipRoot = true;
88
            $preloaded = new Preloaded();
89
            $preloaded->setSchemaData($baseName, $dataValue);
90
            $data = new \stdClass();
91
            foreach ($this->ptrInSchema as $i => $ptr) {
92
                $data->oneOf[$i] = (object)[Schema::PROP_REF => $baseName . $ptr];
93
            }
94
            $schema = Schema::import($data, new Context($preloaded));
95
        }
96
97
        $appPath = realpath($this->nsPath);
98
        if (!$appPath) {
99
            $this->response->error('Could not find directory ' . $this->nsPath);
100
            throw new ExitCode('', 1);
101
        }
102
        $appNs = $this->ns;
103
104
        $app = new PhpApp();
105
        $app->setNamespaceRoot($appNs, '.');
106
107
        $builder = new PhpBuilder();
108
        $builder->buildSetters = $this->setters;
109
        $builder->buildGetters = $this->getters;
110
111
        $builder->makeEnumConstants = !$this->noEnumConst;
112
113
        $builder->classCreatedHook = new ClassHookCallback(function (PhpClass $class, $path, $schema)
114
        use ($app, $appNs, $skipRoot, $baseName) {
115
            if ($skipRoot && '#' === $path) {
116
                return;
117
            }
118
119
            $desc = '';
120
            if ($schema->title) {
121
                $desc = $schema->title;
122
            }
123
            if ($schema->description) {
124
                $desc .= "\n" . $schema->description;
125
            }
126
            if ($fromRefs = $schema->getFromRefs()) {
127
                $desc .= "\nBuilt from " . implode("\n" . ' <- ', $fromRefs);
128
            }
129
            $class->setDescription(trim($desc));
130
131
            $class->setNamespace($appNs);
132
            if ('#' === $path) {
133
                $class->setName($this->rootName);
134
            } else {
135
                if (!empty($fromRefs)) {
136
                    $path = $fromRefs[0];
137
                }
138
                foreach ($this->defPtr as $defPtr) {
139
                    if (isset($baseName)) {
140
                        $baseNameDefPtr = $baseName . $defPtr;
141
                        if ($baseNameDefPtr === substr($path, 0, strlen($baseNameDefPtr))) {
142
                            $path = substr($path, strlen($baseNameDefPtr));
143
                            $className = PhpCode::makePhpClassName($path);
144
                            $class->setName($className);
145
                        }
146
                    }
147
148
                    if ($defPtr === substr($path, 0, strlen($defPtr))) {
149
                        $className = PhpCode::makePhpClassName(substr($path, strlen($defPtr)));
150
                        $class->setName($className);
151
                    }
152
                }
153
            }
154
            $app->addClass($class);
155
        });
156
157
        if (!$schema instanceof Schema) {
158
            $this->response->error('failed to assert Schema type, ' . get_class($schema) . ' received');
159
            throw new ExitCode('', 1);
160
        }
161
        $builder->getType($schema);
162
        $app->store($appPath);
163
        $this->response->success("Classes are generated in " . $appPath);
164
    }
165
}