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 ( cd44a9...cb09cd )
by Cees-Jan
03:49
created

ResourceGenerator::applyPsr2()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 15
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 15
ccs 11
cts 11
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 11
nc 1
nop 1
crap 1
1
<?php
2
declare(strict_types=1);
3
4
namespace WyriHaximus\ApiClient\Tools;
5
6
use Doctrine\Common\Inflector\Inflector;
7
use Exception;
8
use League\CLImate\CLImate;
9
use PhpParser\Builder\Method;
10
use PhpParser\Builder\Property;
11
use PhpParser\BuilderFactory;
12
use PhpParser\PrettyPrinter;
13
use PhpParser\Node;
14
use Symfony\Component\Yaml\Yaml;
15
use Symfony\CS\Config\Config;
16
use Symfony\CS\ConfigAwareInterface;
17
use Symfony\CS\ConfigInterface;
18
use Symfony\CS\FileCacheManager;
19
use Symfony\CS\Fixer;
20
use Symfony\CS\FixerInterface;
21
22
class ResourceGenerator
23
{
24
    protected $climate;
25
26
    /**
27
     * @var Fixer
28
     */
29
    protected $fixer;
30
31
    /**
32
     * @var array
33
     */
34
    protected $fixers;
35
36 2
    public function __construct(CLImate $climate)
37
    {
38 2
        $this->climate = $climate;
39
40 2
        $this->setUpArguments();
41 2
        $this->setUpFixers();
42 2
    }
43
44 2
    protected function setUpArguments()
45
    {
46 2
        $this->climate->arguments->add([
47
            'definition' => [
48
                'description' => 'YAML definition file',
49
                'required'    => true,
50 2
            ],
51
            'path' => [
52
                'description' => 'Path to the resource directory',
53
                'required'    => true,
54
            ],
55
            'sync' => [
56
                'prefix'       => 's',
57
                'longPrefix'   => 'sync',
58
                'defaultValue' => true,
59
                'noValue'      => false,
60
                'description'  => 'Don\'t generate Sync resource',
61
                'castTo'       => 'bool',
62
            ],
63
            'async' => [
64
                'prefix'       => 'as',
65
                'longPrefix'   => 'async',
66
                'defaultValue' => true,
67
                'noValue'      => false,
68
                'description'  => 'Don\'t generate Async resource',
69
                'castTo'       => 'bool',
70
            ],
71
        ]);
72 2
    }
73
74 2
    protected function setUpFixers()
75
    {
76 2
        $this->fixer = new Fixer();
77 2
        $this->fixer->registerCustomFixers([
78 2
            new Fixer\Symfony\ExtraEmptyLinesFixer(),
79 2
            new Fixer\Symfony\SingleBlankLineBeforeNamespaceFixer(),
80 2
            new Fixer\PSR0\Psr0Fixer(),
81 2
            new Fixer\PSR1\EncodingFixer(),
82 2
            new Fixer\PSR1\ShortTagFixer(),
83 2
            new Fixer\PSR2\BracesFixer(),
84 2
            new Fixer\PSR2\ElseifFixer(),
85 2
            new Fixer\PSR2\EofEndingFixer(),
86 2
            new Fixer\PSR2\FunctionCallSpaceFixer(),
87 2
            new Fixer\PSR2\FunctionDeclarationFixer(),
88 2
            new Fixer\PSR2\IndentationFixer(),
89 2
            new Fixer\PSR2\LineAfterNamespaceFixer(),
90 2
            new Fixer\PSR2\LinefeedFixer(),
91 2
            new Fixer\PSR2\LowercaseConstantsFixer(),
92 2
            new Fixer\PSR2\LowercaseKeywordsFixer(),
93 2
            new Fixer\PSR2\MethodArgumentSpaceFixer(),
94 2
            new Fixer\PSR2\MultipleUseFixer(),
95 2
            new Fixer\PSR2\ParenthesisFixer(),
96 2
            new Fixer\PSR2\PhpClosingTagFixer(),
97 2
            new Fixer\PSR2\SingleLineAfterImportsFixer(),
98 2
            new Fixer\PSR2\TrailingSpacesFixer(),
99 2
            new Fixer\PSR2\VisibilityFixer(),
100 2
            new Fixer\Contrib\NewlineAfterOpenTagFixer(),
101
        ]);
102 2
        $config = Config::create()->
103 2
        fixers($this->fixer->getFixers())
104
        ;
105 2
        $this->fixer->addConfig($config);
106 2
        $this->fixers = $this->prepareFixers($config);
107 2
    }
108
109 1
    public function run()
110
    {
111 1
        $yaml = $this->readYaml($this->climate->arguments->get('definition'));
112
113 1
        $class = explode('\\', $yaml['class']);
114 1
        $namespace = explode('\\', $yaml['namespace']);
115
116 1
        $yaml['class'] = array_pop($class);
117 1
        $yaml['namespace'] = implode('\\', array_merge($namespace, $class));
118
119 1
        $classNamespacePadding = implode(DIRECTORY_SEPARATOR, $class);
120
121 1
        $this->save(
122 1
            $this->climate->arguments->get('path') .
123 1
                DIRECTORY_SEPARATOR .
124 1
                $classNamespacePadding .
125 1
                DIRECTORY_SEPARATOR,
126 1
            $yaml['class'] .
127 1
                '.php',
128 1
            $this->createBaseClass($yaml)
129
        );
130 1
        $this->save(
131 1
            $this->climate->arguments->get('path') .
132 1
                DIRECTORY_SEPARATOR .
133 1
                $classNamespacePadding .
134 1
                DIRECTORY_SEPARATOR,
135 1
            $yaml['class'] .
136 1
                'Interface.php',
137 1
            $this->createInterface($yaml)
138
        );
139 1
        $this->save(
140 1
            $this->climate->arguments->get('path') .
141 1
                DIRECTORY_SEPARATOR .
142 1
                'Async' .
143 1
                DIRECTORY_SEPARATOR .
144 1
                $classNamespacePadding .
145 1
                DIRECTORY_SEPARATOR,
146 1
            $yaml['class'] .
147 1
                '.php',
148 1
            $this->createExtendingClass('Async', $yaml)
149
        );
150 1
        $this->save(
151 1
            $this->climate->arguments->get('path') .
152 1
                DIRECTORY_SEPARATOR .
153 1
                'Sync' .
154 1
                DIRECTORY_SEPARATOR .
155 1
                $classNamespacePadding .
156 1
                DIRECTORY_SEPARATOR,
157 1
            $yaml['class'] .
158 1
                '.php',
159 1
            $this->createExtendingClass('Sync', $yaml)
160
        );
161 1
    }
162
163 1
    protected function readYaml(string $filename): array
164
    {
165 1
        return Yaml::parse(file_get_contents($filename));
166
    }
167
168 1
    protected function createBaseClass(array $yaml)
169
    {
170 1
        $factory = new BuilderFactory;
171
172 1
        $class = $factory->class($yaml['class'])
173 1
            ->implement($yaml['class'] . 'Interface')
174 1
            ->makeAbstract();
175 1
        $class->addStmt(
176 1
            new Node\Stmt\TraitUse([
177 1
                new Node\Name('TransportAwareTrait')
178
            ])
179
        );
180
181 1
        foreach ($yaml['properties'] as $name => $details) {
182 1
            $type = $details;
183 1
            if (is_array($details)) {
184 1
                $type = $details['type'];
185
            }
186 1
            $class->addStmt($this->createProperty($factory, $type, $name, $details));
187 1
            $class->addStmt($this->createMethod($factory, $type, $name, $details));
188
        }
189
190 1
        $node = $factory->namespace($yaml['namespace'])
191 1
            ->addStmt($factory->use('WyriHaximus\ApiClient\Resource\TransportAwareTrait'))
192 1
            ->addStmt($class)
193
194 1
            ->getNode()
195
        ;
196
197 1
        $prettyPrinter = new PrettyPrinter\Standard();
198 1
        return $prettyPrinter->prettyPrintFile([
199 1
            $node
200 1
        ]) . PHP_EOL;
201
    }
202
203 1
    protected function createInterface(array $yaml)
204
    {
205 1
        $factory = new BuilderFactory;
206
207 1
        $class = $factory->interface($yaml['class'] . 'Interface')
208 1
            ->extend('ResourceInterface');
209
210 1
        foreach ($yaml['properties'] as $name => $details) {
211 1
            $type = $details;
212 1
            if (is_array($details)) {
213 1
                $type = $details['type'];
214
            }
215 1
            $class->addStmt($this->createMethod($factory, $type, $name, $details));
216
        }
217
218 1
        $node = $factory->namespace($yaml['namespace'])
219 1
            ->addStmt($factory->use('WyriHaximus\ApiClient\Resource\ResourceInterface'))
220 1
            ->addStmt($class)
221 1
            ->getNode()
222
        ;
223
224 1
        $prettyPrinter = new PrettyPrinter\Standard();
225 1
        return $prettyPrinter->prettyPrintFile([
226 1
            $node
227 1
        ]) . PHP_EOL;
228
    }
229
230 1
    protected function createProperty(BuilderFactory $factory, string $type, string $name, $details): Property
231
    {
232 1
        $property = $factory->property($name)
233 1
            ->makeProtected()
234 1
            ->setDocComment('/**
235 1
                              * @var ' . $type . '
236 1
                              */');
237 1
        if (isset($details['default'])) {
238 1
            $property->setDefault($details['default']);
239
        }
240
241 1
        return $property;
242
    }
243
244 1
    protected function createMethod(BuilderFactory $factory, string $type, string $name, $details): Method
0 ignored issues
show
Unused Code introduced by
The parameter $details is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
245
    {
246 1
        return $factory->method(Inflector::camelize($name))
247 1
            ->makePublic()
248 1
            ->setReturnType($type)
249 1
            ->setDocComment('/**
250 1
                              * @return ' . $type . '
251 1
                              */')
252 1
            ->addStmt(
253 1
                new Node\Stmt\Return_(
254 1
                    new Node\Expr\PropertyFetch(
255 1
                        new Node\Expr\Variable('this'),
256
                        $name
257
                    )
258
                )
259
            );
260
    }
261
262 1
    protected function createExtendingClass(string $type, array $yaml)
263
    {
264 1
        $factory = new BuilderFactory;
265
266 1
        $class = $factory->class($yaml['class'])
267 1
            ->extend('Base' . $yaml['class']);
268
269 1
        $class->addStmt($factory->method('refresh')
270 1
            ->makePublic()
271 1
            ->setReturnType($yaml['class'])
272 1
            ->addStmt(
273 1
                new Node\Stmt\Return_(
274 1
                    new Node\Expr\MethodCall(
275 1
                        new Node\Expr\Variable('this'),
276 1
                        'wait',
277
                        [
0 ignored issues
show
Documentation introduced by
array(new \PhpParser\Nod...r\String_('refresh')))) is of type array<integer,object<Php...e\\Expr\\MethodCall>"}>, 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...
278 1
                            new Node\Expr\MethodCall(
279 1
                                new Node\Expr\Variable('this'),
280 1
                                'callAsync',
281
                                [
0 ignored issues
show
Documentation introduced by
array(new \PhpParser\Nod...lar\String_('refresh')) is of type array<integer,object<Php...de\\Scalar\\String_>"}>, 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...
282 1
                                    new Node\Scalar\String_('refresh'),
283
                                ]
284
                            ),
285
                        ]
286
                    )
287
                )
288
            ));
289
290 1
        $node = $factory->namespace($yaml['namespace'] . '\\' . $type)
291 1
            ->addStmt($factory->use($yaml['namespace'] . '\\' . $yaml['class'])->as('Base' . $yaml['class']))
292 1
            ->addStmt($class)
293
294 1
            ->getNode()
295
        ;
296
297 1
        $prettyPrinter = new PrettyPrinter\Standard();
298 1
        return $prettyPrinter->prettyPrintFile([
299 1
            $node
300 1
        ]) . PHP_EOL;
301
    }
302
303 1
    protected function save(string $directory, string $fileName, string $fileContents)
304
    {
305 1
        $fileName = str_replace('\\', DIRECTORY_SEPARATOR, $fileName);
306 1
        if (file_exists($directory . $fileName)) {
307
            return;
308
        }
309
310 1
        $path = $directory . $fileName;
311 1
        $pathChunks = explode(DIRECTORY_SEPARATOR, $path);
312 1
        array_pop($pathChunks);
313 1
        $path = implode(DIRECTORY_SEPARATOR, $pathChunks);
314 1
        if (!file_exists($path)) {
315 1
            mkdir($path, 0777, true);
316
        }
317
318 1
        if (!file_exists($path)) {
319
            throw new Exception('Unable to create: ' . $path);
320
        }
321
322 1
        file_put_contents($directory . $fileName, $fileContents);
323
324
        do {
325 1
            usleep(500);
326 1
        } while (!file_exists($directory . $fileName));
327
328 1
        $this->applyPsr2($directory . $fileName);
329 1
    }
330
331 1
    protected function applyPsr2($fileName)
332
    {
333 1
        $file = new \SplFileInfo($fileName);
334 1
        $this->fixer->fixFile(
335
            $file,
336 1
            $this->fixers,
337 1
            false,
338 1
            false,
339 1
            new FileCacheManager(
340 1
                false,
341 1
                '',
342 1
                $this->fixers
343
            )
344
        );
345 1
    }
346
347
348
    /**
349
     * @param ConfigInterface $config
350
     *
351
     * @return FixerInterface[]
352
     */
353 2
    private function prepareFixers(ConfigInterface $config)
354
    {
355 2
        $fixers = $config->getFixers();
356
357 2
        foreach ($fixers as $fixer) {
358 2
            if ($fixer instanceof ConfigAwareInterface) {
359 2
                $fixer->setConfig($config);
360
            }
361
        }
362
363 2
        return $fixers;
364
    }
365
}
366