Completed
Push — master ( b1e8a1...edf0e8 )
by Nikola
03:49
created

BuilderGenerator::create()   B

Complexity

Conditions 4
Paths 8

Size

Total Lines 107
Code Lines 49

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 0
loc 107
ccs 0
cts 89
cp 0
rs 8.1935
c 1
b 0
f 0
cc 4
eloc 49
nc 8
nop 3
crap 20

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
3
namespace RunOpenCode\AbstractBuilder\Generator;
4
5
use PhpParser\BuilderFactory;
6
use PhpParser\Parser;
7
use PhpParser\ParserFactory;
8
use PhpParser\PrettyPrinter\Standard;
9
use RunOpenCode\AbstractBuilder\Ast\Metadata\ClassMetadata;
10
use RunOpenCode\AbstractBuilder\Ast\Metadata\FileMetadata;
11
use RunOpenCode\AbstractBuilder\Ast\Metadata\MethodMetadata;
12
use RunOpenCode\AbstractBuilder\Ast\MetadataLoader;
13
use RunOpenCode\AbstractBuilder\Command\Question\ClassChoice;
14
use RunOpenCode\AbstractBuilder\ReflectiveAbstractBuilder;
15
use RunOpenCode\AbstractBuilder\Utils\ClassUtils;
16
use PHPParser\Node;
17
18
class BuilderGenerator
19
{
20
    /**
21
     * @var BuilderFactory
22
     */
23
    private $factory;
24
25
    /**
26
     * @var Parser
27
     */
28
    private $parser;
29
30
    /**
31
     * @var MetadataLoader
32
     */
33
    private $loader;
34
35
    /**
36
     * @var Standard
37
     */
38
    private $printer;
39
40
    public function __construct()
41
    {
42
        $this->factory = new BuilderFactory();
43
        $this->parser = (new ParserFactory())->create(ParserFactory::ONLY_PHP7);
44
        $this->loader = new MetadataLoader();
45
        $this->printer = new Standard();
46
    }
47
48
    public function create(ClassChoice $buildingClassChoice, $builderFilename, $builderClassName)
49
    {
50
51
        $namespace = $this->factory->namespace($ns = ClassUtils::getNamespace($builderClassName));
52
53
        $namespace->addStmt($this->factory->use(ReflectiveAbstractBuilder::class));
54
55
        $builderClass = $this->factory->class($builderClassName)
56
            ->extend('ReflectiveAbstractBuilder')
57
            ->setDocComment(sprintf(
58
                '
59
/**
60
 * Class %s
61
 *
62
 * This class is implementation of builder pattern 
63
 * for class %s. 
64
 *  
65
 * This class is autogenerated by runopencode/abstract-builder library.
66
 *
67
 * @package %s
68
 *
69
 * @see %s
70
 * @see https://en.wikipedia.org/wiki/Builder_pattern
71
 */', $builderClassName, $buildingClassChoice->getClass()->getName(), $ns, ReflectiveAbstractBuilder::class));
72
73
        if ($buildingClassChoice->getClass()->isFinal()) {
74
            $builderClass->makeFinal();
75
        }
76
77
        if ($buildingClassChoice->getClass()->isAbstract()) {
78
            $builderClass->makeAbstract();
79
        }
80
81
        if (!$buildingClassChoice->getClass()->isAbstract()) {
82
83
            $buildMethod = $this->factory->method('build')
84
                ->makePublic()
85
                ->addStmts($this->parser->parse(
0 ignored issues
show
Bug introduced by
It seems like $this->parser->parse('<?...turn parent::build();') targeting PhpParser\Parser::parse() can also be of type null; however, PhpParser\Builder\Declaration::addStmts() does only seem to accept array, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
86
                    <<<'CODE'
87
<?php return parent::build();
88
CODE
89
90
                ))
91
                ->setDocComment(sprintf(
92
                    '
93
/**
94
 * Builds new instance of %s from provided arguments. 
95
 *
96
 * @return %s
97
 */', $buildingClassChoice->getClass()->getName(), $buildingClassChoice->getClass()->getName()
98
                ));
99
100
            $builderClass->addStmt($buildMethod->getNode());
101
        }
102
103
        $getObjectFqcnMethod = $this->factory->method('getObjectFqcn')
104
            ->makeProtected()
105
            ->addStmt(new Node\Stmt\Return_(new Node\Scalar\String_($builderClassName)))
106
            ->setDocComment(
107
                '
108
/**
109
 * {@inheritdoc}
110
 */'
111
            );
112
113
        $builderClass->addStmt($getObjectFqcnMethod->getNode());
114
115
        $configureParametersMethod = $this->factory->method('configureParameters')
116
            ->makeProtected()
117
            ->addStmts($this->parser->parse(
0 ignored issues
show
Bug introduced by
It seems like $this->parser->parse('<?...ere return $defaults;') targeting PhpParser\Parser::parse() can also be of type null; however, PhpParser\Builder\Declaration::addStmts() does only seem to accept array, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
118
                <<<'CODE'
119
<?php $defaults = parent::configureParameters();
120
// Modify default values here
121
return $defaults;
122
CODE
123
124
            ))
125
            ->setDocComment(
126
                '
127
/**
128
 * You can override default building parameter values here 
129
 *
130
 * {@inheritdoc}
131
 */'
132
            );
133
134
        $builderClass->addStmt($configureParametersMethod->getNode());
135
136
        $namespace->addStmt($builderClass->getNode());
137
138
        $classMetadata = new ClassMetadata(
139
            $builderClassName,
140
            $this->loader->load(ReflectiveAbstractBuilder::class)->getClass(ReflectiveAbstractBuilder::class),
141
            [],
142
            $buildingClassChoice->getClass()->isFinal(),
143
            $buildingClassChoice->getClass()->isAbstract(),
144
            [
145
                MethodMetadata::fromClassMethod($configureParametersMethod->getNode()),
146
                MethodMetadata::fromClassMethod($getObjectFqcnMethod->getNode())
147
            ],
148
            $builderClass->getNode()
149
        );
150
151
        $fileMetadata = new FileMetadata($builderFilename, [], [$classMetadata], [], [$namespace->getNode()]);
152
153
        return $fileMetadata;
154
    }
155
156
    public function write(FileMetadata $file)
157
    {
158
        return $this->printer->prettyPrint($file->getAst());
159
    }
160
}
161