GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( 65e9a9...017ab2 )
by Cees-Jan
08:12
created

BaseClassGenerator::createProperty()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 7

Duplication

Lines 12
Ratio 100 %

Importance

Changes 0
Metric Value
cc 2
eloc 7
nc 2
nop 3
dl 12
loc 12
rs 9.4285
c 0
b 0
f 0
1
<?php declare(strict_types=1);
2
3
namespace ApiClients\Tools\ResourceGenerator\FileGenerators;
4
5
use ApiClients\Foundation\Hydrator\Annotations\EmptyResource;
6
use ApiClients\Foundation\Resource\AbstractResource;
7
use ApiClients\Tools\ResourceGenerator\FileGeneratorInterface;
8
use Doctrine\Common\Inflector\Inflector;
9
use PhpParser\Builder\Method;
10
use PhpParser\Builder\Property;
11
use PhpParser\BuilderFactory;
12
use PhpParser\Node;
13
use function ApiClients\Tools\ResourceGenerator\exists;
14
15
final class BaseClassGenerator implements FileGeneratorInterface
16
{
17
    /**
18
     * @var array
19
     */
20
    protected $yaml;
21
22
    /**
23
     * @var BuilderFactory
24
     */
25
    protected $factory;
26
27
    /**
28
     * @var string[]
29
     */
30
    protected $docBlock = [];
31
32
    /**
33
     * @var array
34
     */
35
    protected $uses = [
36
        AbstractResource::class => true,
37
        EmptyResource::class => true,
38
    ];
39
40
    /**
41
     * InterfaceGenerator constructor.
42
     * @param array $yaml
43
     */
44
    public function __construct(array $yaml)
45
    {
46
        $this->yaml = $yaml;
47
        if (isset($this->yaml['uses']) && is_array($this->yaml['uses'])) {
48
            $this->uses += $this->yaml['uses'];
49
        }
50
        $this->factory = new BuilderFactory();
51
    }
52
53
    /**
54
     * @return string
55
     */
56 View Code Duplication
    public function getFilename(): string
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
57
    {
58
        return $this->yaml['src']['path'] .
59
            DIRECTORY_SEPARATOR .
60
            str_replace('\\', DIRECTORY_SEPARATOR, $this->yaml['class']) .
61
            '.php'
62
        ;
63
    }
64
65
    /**
66
     * @return Node
67
     */
68
    public function generate(): Node
69
    {
70
        $classChunks = explode('\\', $this->yaml['class']);
71
        $className = array_pop($classChunks);
72
        $namespace = $this->yaml['src']['namespace'];
73
        if (count($classChunks) > 0) {
74
            $namespace .= '\\' . implode('\\', $classChunks);
75
            $namespace = str_replace('\\\\', '\\', $namespace);
76
        }
77
78
        $class = $this->factory->class($className)
79
            ->implement($className . 'Interface')
80
            ->extend('AbstractResource')
81
            ->makeAbstract();
82
83
        $stmt = $this->factory->namespace($namespace);
84
        foreach ($this->yaml['properties'] as $name => $details) {
85
            $stmt = $this->processProperty($class, $stmt, $name, $details);
86
        }
87
88
        ksort($this->uses);
89
        foreach ($this->uses as $useClass => $bool) {
90
            $stmt = $stmt
91
                ->addStmt($this->factory->use($useClass))
92
            ;
93
        }
94
95
        if (isset($this->yaml['annotations'])) {
96
            ksort($this->yaml['annotations']);
97
            foreach ($this->yaml['annotations'] as $annotation => $details) {
98
                $nestedResources = [];
99
                foreach ($details as $key => $value) {
100
                    $nestedResources[] = $key . '="' . $value . '"';
101
                }
102
                $this->docBlock[] = '@' .
103
                    $annotation .
104
                    "(\r\n *     " .
105
                    implode(",\r\n *     ", $nestedResources) .
106
                    "\r\n * )"
107
                ;
108
            }
109
        }
110
111
        $namespacePrefix = ltrim(implode('\\', $classChunks) . '\\', '\\');
112
        $this->docBlock[] = '@EmptyResource("' . $namespacePrefix . 'Empty' . $className . '")';
113
114
        if (count($this->docBlock) > 0) {
115
            $class->setDocComment("/**\r\n * " . implode("\r\n * ", $this->docBlock) . "\r\n */");
116
        }
117
118
        return $stmt->addStmt($class)->getNode();
119
    }
120
121
    /**
122
     * @param \PhpParser\Builder\Class_ $class
123
     */
124
    protected function processProperty($class, $stmt, $name, $details)
125
    {
126
        if (is_string($details)) {
127
            $types = explode('|', $details);
128
            foreach ($types as $type) {
129
                if (exists($type)) {
130
                    $this->uses[$type] = true;
131
                }
132
            }
133
134
            $class->addStmt($this->createProperty($details, $name, $details));
135
            $methodName = Inflector::camelize($name);
136
            $class->addStmt($this->createMethod($types, $name, $methodName, $details));
137
            return $stmt;
138
        }
139
140
        $types = explode('|', $details['type']);
141
        foreach ($types as $type) {
142
            if (exists($type)) {
143
                $this->uses[$type] = true;
144
            }
145
        }
146
        if (isset($details['wrap']) && exists($details['wrap'])) {
147
            $this->uses[$details['wrap']] = true;
148
        }
149
150
        $class->addStmt($this->createProperty($details['type'], $name, $details));
151
        if (isset($details['wrap'])) {
152
            $class->addStmt($this->createProperty($details['wrap'], $name . '_wrapped', $details));
153
        }
154
155
        $methodName = Inflector::camelize($name);
156
        if (isset($details['method'])) {
157
            $methodName = $details['method'];
158
        }
159
        $class->addStmt($this->createMethod($types, $name, $methodName, $details));
160
161
        return $stmt;
162
    }
163
164 View Code Duplication
    protected function createProperty(string $type, string $name, $details): Property
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
165
    {
166
        $property = $this->factory->property($name)
167
            ->makeProtected()
168
            ->setDocComment("/**\r\n * @var " . $type . "\r\n */")
169
        ;
170
        if (isset($details['default'])) {
171
            $property->setDefault($details['default']);
172
        }
173
174
        return $property;
175
    }
176
177
    protected function createMethod(
178
        array $types,
179
        string $name,
180
        string $methodName,
181
        $details
182
    ): Method {
183
        $stmts = [
184
            new Node\Stmt\Return_(
185
                new Node\Expr\PropertyFetch(
186
                    new Node\Expr\Variable('this'),
187
                    $name
188
                )
189
            )
190
        ];
191
192
        if (isset($details['wrap'])) {
193
            $stmts = [];
194
            $stmts[] = new Node\Stmt\If_(
195
                new Node\Expr\Instanceof_(
196
                    new Node\Expr\PropertyFetch(
197
                        new Node\Expr\Variable('this'),
198
                        $name . '_wrapped'
199
                    ),
200
                    new Node\Name($details['wrap'])
201
                ),
202
                [
203
                    'stmts' => [
204
                        new Node\Stmt\Return_(
205
                            new Node\Expr\PropertyFetch(
206
                                new Node\Expr\Variable('this'),
207
                                $name . '_wrapped'
208
                            )
209
                        ),
210
                    ],
211
                ]
212
            );
213
            $stmts[] = new Node\Expr\Assign(
214
                new Node\Expr\PropertyFetch(
215
                    new Node\Expr\Variable('this'),
216
                    $name . '_wrapped'
217
                ),
218
                new Node\Expr\New_(
219
                    new Node\Name($details['wrap']),
220
                    [
0 ignored issues
show
Documentation introduced by
array(new \PhpParser\Nod...riable('this'), $name)) is of type array<integer,object<Php...Expr\\PropertyFetch>"}>, but the function expects a array<integer,object<PhpParser\Node\Arg>>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
221
                        new Node\Expr\PropertyFetch(
222
                            new Node\Expr\Variable('this'),
223
                            $name
224
                        ),
225
                    ]
226
                )
227
            );
228
            $stmts[] = new Node\Stmt\Return_(
229
                new Node\Expr\PropertyFetch(
230
                    new Node\Expr\Variable('this'),
231
                    $name . '_wrapped'
232
                )
233
            );
234
        }
235
236
        $method = $this->factory->method($methodName)
237
            ->makePublic()
238
            ->setDocComment('/**
239
                              * @return ' . implode('|',$types) . '
240
                              */')
241
            ->addStmts($stmts);
242
        if (count($types) === 1) {
243
            $method = $method->setReturnType($types[0]);
244
        }
245
        return $method;
246
    }
247
}
248