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 ( cb09cd...fe481e )
by Cees-Jan
02:38
created

ResourceGenerator::run()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 89
Code Lines 65

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 53
CRAP Score 1

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 89
ccs 53
cts 53
cp 1
rs 8.5731
cc 1
eloc 65
nc 1
nop 0
crap 1

How to fix   Long Method   

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
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
use WyriHaximus\ApiClient\Resource\ResourceInterface;
22
23
class ResourceGenerator
24
{
25
    protected $climate;
26
27
    /**
28
     * @var Fixer
29
     */
30
    protected $fixer;
31
32
    /**
33
     * @var array
34
     */
35
    protected $fixers;
36
37 2
    public function __construct(CLImate $climate)
38
    {
39 2
        $this->climate = $climate;
40
41 2
        $this->setUpArguments();
42 2
        $this->setUpFixers();
43 2
    }
44
45 2
    protected function setUpArguments()
46
    {
47 2
        $this->climate->arguments->add([
48
            'definition' => [
49
                'description' => 'YAML definition file',
50
                'required'    => true,
51 2
            ],
52
            'path' => [
53
                'description' => 'Path to the resource directory',
54
                'required'    => true,
55
            ],
56
            'sync' => [
57
                'prefix'       => 's',
58
                'longPrefix'   => 'sync',
59
                'defaultValue' => true,
60
                'noValue'      => false,
61
                'description'  => 'Don\'t generate Sync resource',
62
                'castTo'       => 'bool',
63
            ],
64
            'async' => [
65
                'prefix'       => 'as',
66
                'longPrefix'   => 'async',
67
                'defaultValue' => true,
68
                'noValue'      => false,
69
                'description'  => 'Don\'t generate Async resource',
70
                'castTo'       => 'bool',
71
            ],
72
        ]);
73 2
    }
74
75 2
    protected function setUpFixers()
76
    {
77 2
        $this->fixer = new Fixer();
78 2
        $this->fixer->registerCustomFixers([
79 2
            new Fixer\Symfony\ExtraEmptyLinesFixer(),
80 2
            new Fixer\Symfony\SingleBlankLineBeforeNamespaceFixer(),
81 2
            new Fixer\PSR0\Psr0Fixer(),
82 2
            new Fixer\PSR1\EncodingFixer(),
83 2
            new Fixer\PSR1\ShortTagFixer(),
84 2
            new Fixer\PSR2\BracesFixer(),
85 2
            new Fixer\PSR2\ElseifFixer(),
86 2
            new Fixer\PSR2\EofEndingFixer(),
87 2
            new Fixer\PSR2\FunctionCallSpaceFixer(),
88 2
            new Fixer\PSR2\FunctionDeclarationFixer(),
89 2
            new Fixer\PSR2\IndentationFixer(),
90 2
            new Fixer\PSR2\LineAfterNamespaceFixer(),
91 2
            new Fixer\PSR2\LinefeedFixer(),
92 2
            new Fixer\PSR2\LowercaseConstantsFixer(),
93 2
            new Fixer\PSR2\LowercaseKeywordsFixer(),
94 2
            new Fixer\PSR2\MethodArgumentSpaceFixer(),
95 2
            new Fixer\PSR2\MultipleUseFixer(),
96 2
            new Fixer\PSR2\ParenthesisFixer(),
97 2
            new Fixer\PSR2\PhpClosingTagFixer(),
98 2
            new Fixer\PSR2\SingleLineAfterImportsFixer(),
99 2
            new Fixer\PSR2\TrailingSpacesFixer(),
100 2
            new Fixer\PSR2\VisibilityFixer(),
101 2
            new Fixer\Contrib\NewlineAfterOpenTagFixer(),
102 2
            new EmptyLineAboveDocblocksFixer(),
103
        ]);
104 2
        $config = Config::create()->
105 2
        fixers($this->fixer->getFixers())
106
        ;
107 2
        $this->fixer->addConfig($config);
108 2
        $this->fixers = $this->prepareFixers($config);
109 2
    }
110
111 1
    public function run()
112
    {
113 1
        $yaml = $this->readYaml($this->climate->arguments->get('definition'));
114
115 1
        $namespacePadding = explode('\\', $yaml['class']);
116 1
        $namespace = explode('\\', $yaml['namespace']);
117
118 1
        $yaml['class'] = array_pop($namespacePadding);
119 1
        $yaml['namespace'] = implode('\\', array_merge($namespace, $namespacePadding));
120
121 1
        $namespacePathPadding = implode(DIRECTORY_SEPARATOR, $namespacePadding);
122 1
        $baseClass = implode(
123 1
            '\\',
124
            array_merge(
125
                $namespace,
126
                $namespacePadding,
127
                [
128 1
                    $yaml['class']
129
                ]
130
            )
131
        );
132
133 1
        $this->save(
134 1
            $this->climate->arguments->get('path') .
135 1
                DIRECTORY_SEPARATOR .
136 1
                $namespacePathPadding .
137 1
                DIRECTORY_SEPARATOR,
138 1
            $yaml['class'] .
139 1
                '.php',
140 1
            $this->createBaseClass($yaml)
141
        );
142 1
        $this->save(
143 1
            $this->climate->arguments->get('path') .
144 1
                DIRECTORY_SEPARATOR .
145 1
                $namespacePathPadding .
146 1
                DIRECTORY_SEPARATOR,
147 1
            $yaml['class'] .
148 1
                'Interface.php',
149 1
            $this->createInterface($yaml)
150
        );
151 1
        $this->save(
152 1
            $this->climate->arguments->get('path') .
153 1
                DIRECTORY_SEPARATOR .
154 1
                'Async' .
155 1
                DIRECTORY_SEPARATOR .
156 1
                $namespacePathPadding .
157 1
                DIRECTORY_SEPARATOR,
158 1
            $yaml['class'] .
159 1
                '.php',
160 1
            $this->createExtendingClass(
161
                implode(
162 1
                    '\\',
163
                    array_merge(
164
                        $namespace,
165
                        [
166 1
                            'Async',
167
                        ],
168
                        $namespacePadding
169
                    )
170
                ),
171 1
                $yaml['class'],
172
                $baseClass
173
            )
174
        );
175 1
        $this->save(
176 1
            $this->climate->arguments->get('path') .
177 1
                DIRECTORY_SEPARATOR .
178 1
                'Sync' .
179 1
                DIRECTORY_SEPARATOR .
180 1
                $namespacePathPadding .
181 1
                DIRECTORY_SEPARATOR,
182 1
            $yaml['class'] .
183 1
                '.php',
184 1
            $this->createExtendingClass(
185
                implode(
186 1
                    '\\',
187
                    array_merge(
188
                        $namespace,
189
                        [
190 1
                            'Sync',
191
                        ],
192
                        $namespacePadding
193
                    )
194
                ),
195 1
                $yaml['class'],
196
                $baseClass
197
            )
198
        );
199 1
    }
200
201 1
    protected function readYaml(string $filename): array
202
    {
203 1
        return Yaml::parse(file_get_contents($filename));
204
    }
205
206 1
    protected function createBaseClass(array $yaml)
207
    {
208 1
        $factory = new BuilderFactory;
209
210 1
        $class = $factory->class($yaml['class'])
211 1
            ->implement($yaml['class'] . 'Interface')
212 1
            ->makeAbstract();
213 1
        $class->addStmt(
214 1
            new Node\Stmt\TraitUse([
215 1
                new Node\Name('TransportAwareTrait')
216
            ])
217
        );
218
219 1
        foreach ($yaml['properties'] as $name => $details) {
220 1
            $type = $details;
221 1
            if (is_array($details)) {
222 1
                $type = $details['type'];
223
            }
224 1
            $class->addStmt($this->createProperty($factory, $type, $name, $details));
225 1
            $class->addStmt($this->createMethod($factory, $type, $name, $details));
226
        }
227
228 1
        $node = $factory->namespace($yaml['namespace'])
229 1
            ->addStmt($factory->use('WyriHaximus\ApiClient\Resource\TransportAwareTrait'))
230 1
            ->addStmt($class)
231
232 1
            ->getNode()
233
        ;
234
235 1
        $prettyPrinter = new PrettyPrinter\Standard();
236 1
        return $prettyPrinter->prettyPrintFile([
237 1
            $node
238 1
        ]) . PHP_EOL;
239
    }
240
241 1
    protected function createInterface(array $yaml)
242
    {
243 1
        $factory = new BuilderFactory;
244
245 1
        $class = $factory->interface($yaml['class'] . 'Interface')
246 1
            ->extend('ResourceInterface');
247
248 1
        foreach ($yaml['properties'] as $name => $details) {
249 1
            $type = $details;
250 1
            if (is_array($details)) {
251 1
                $type = $details['type'];
252
            }
253 1
            $class->addStmt($this->createMethod($factory, $type, $name, $details));
254
        }
255
256 1
        $node = $factory->namespace($yaml['namespace'])
257 1
            ->addStmt($factory->use(ResourceInterface::class))
258 1
            ->addStmt($class)
259 1
            ->getNode()
260
        ;
261
262 1
        $prettyPrinter = new PrettyPrinter\Standard();
263 1
        return $prettyPrinter->prettyPrintFile([
264 1
            $node
265 1
        ]) . PHP_EOL;
266
    }
267
268 1
    protected function createProperty(BuilderFactory $factory, string $type, string $name, $details): Property
269
    {
270 1
        $property = $factory->property($name)
271 1
            ->makeProtected()
272 1
            ->setDocComment('/**
273 1
                              * @var ' . $type . '
274 1
                              */');
275 1
        if (isset($details['default'])) {
276 1
            $property->setDefault($details['default']);
277
        }
278
279 1
        return $property;
280
    }
281
282 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...
283
    {
284 1
        return $factory->method(Inflector::camelize($name))
285 1
            ->makePublic()
286 1
            ->setReturnType($type)
287 1
            ->setDocComment('/**
288 1
                              * @return ' . $type . '
289 1
                              */')
290 1
            ->addStmt(
291 1
                new Node\Stmt\Return_(
292 1
                    new Node\Expr\PropertyFetch(
293 1
                        new Node\Expr\Variable('this'),
294
                        $name
295
                    )
296
                )
297
            );
298
    }
299
300 1
    protected function createExtendingClass(string $namespace, string $className, string $baseClass)
301
    {
302 1
        $factory = new BuilderFactory;
303
304 1
        $class = $factory->class($className)
305 1
            ->extend('Base' . $className);
306
307 1
        $class->addStmt($factory->method('refresh')
308 1
            ->makePublic()
309 1
            ->setReturnType($className)
310 1
            ->addStmt(
311 1
                new Node\Stmt\Return_(
312 1
                    new Node\Expr\MethodCall(
313 1
                        new Node\Expr\Variable('this'),
314 1
                        'wait',
315
                        [
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...
316 1
                            new Node\Expr\MethodCall(
317 1
                                new Node\Expr\Variable('this'),
318 1
                                'callAsync',
319
                                [
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...
320 1
                                    new Node\Scalar\String_('refresh'),
321
                                ]
322
                            ),
323
                        ]
324
                    )
325
                )
326
            ));
327
328 1
        $node = $factory->namespace($namespace)
329 1
            ->addStmt($factory->use($baseClass)->as('Base' . $className))
330 1
            ->addStmt($class)
331
332 1
            ->getNode()
333
        ;
334
335 1
        $prettyPrinter = new PrettyPrinter\Standard();
336 1
        return $prettyPrinter->prettyPrintFile([
337 1
            $node
338 1
        ]) . PHP_EOL;
339
    }
340
341 1
    protected function save(string $directory, string $fileName, string $fileContents)
342
    {
343 1
        $fileName = str_replace('\\', DIRECTORY_SEPARATOR, $fileName);
344 1
        if (file_exists($directory . $fileName)) {
345
            return;
346
        }
347
348 1
        $path = $directory . $fileName;
349 1
        $pathChunks = explode(DIRECTORY_SEPARATOR, $path);
350 1
        array_pop($pathChunks);
351 1
        $path = implode(DIRECTORY_SEPARATOR, $pathChunks);
352 1
        if (!file_exists($path)) {
353 1
            mkdir($path, 0777, true);
354
        }
355
356 1
        if (!file_exists($path)) {
357
            throw new Exception('Unable to create: ' . $path);
358
        }
359
360 1
        file_put_contents($directory . $fileName, $fileContents);
361
362
        do {
363 1
            usleep(500);
364 1
        } while (!file_exists($directory . $fileName));
365
366 1
        $this->applyPsr2($directory . $fileName);
367 1
    }
368
369 1
    protected function applyPsr2($fileName)
370
    {
371 1
        $file = new \SplFileInfo($fileName);
372 1
        $this->fixer->fixFile(
373
            $file,
374 1
            $this->fixers,
375 1
            false,
376 1
            false,
377 1
            new FileCacheManager(
378 1
                false,
379 1
                '',
380 1
                $this->fixers
381
            )
382
        );
383 1
    }
384
385
386
    /**
387
     * @param ConfigInterface $config
388
     *
389
     * @return FixerInterface[]
390
     */
391 2
    private function prepareFixers(ConfigInterface $config)
392
    {
393 2
        $fixers = $config->getFixers();
394
395 2
        foreach ($fixers as $fixer) {
396 2
            if ($fixer instanceof ConfigAwareInterface) {
397 2
                $fixer->setConfig($config);
398
            }
399
        }
400
401 2
        return $fixers;
402
    }
403
}
404