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

BuilderGenerator::write()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 0
loc 4
ccs 0
cts 4
cp 0
rs 10
c 1
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
crap 2
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