Completed
Push — master ( ed5962...9634df )
by Nikola
03:22
created

ClassBuilder::dump()   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 0
Metric Value
dl 0
loc 4
ccs 0
cts 4
cp 0
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
crap 2
1
<?php
2
/*
3
 * This file is part of the Abstract builder package, an RunOpenCode project.
4
 *
5
 * (c) 2017 RunOpenCode
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
namespace RunOpenCode\AbstractBuilder\Ast;
11
12
use PhpParser\Builder\Class_;
13
use PhpParser\BuilderFactory;
14
use PhpParser\Node;
15
use PhpParser\PrettyPrinter\Standard;
16
use RunOpenCode\AbstractBuilder\ReflectiveAbstractBuilder;
17
18
class ClassBuilder
19
{
20
    /**
21
     * @var ClassMetadata
22
     */
23
    private $builderClass;
24
25
    /**
26
     * @var ClassMetadata
27
     */
28
    private $buildingClass;
29
30
    /**
31
     * @var BuilderFactory
32
     */
33
    private $factory;
34
35
    /**
36
     * @var Node
37
     */
38
    private $namespaceNode;
39
40
    /**
41
     * @var Class_
42
     */
43
    private $classNode;
44
45
    /**
46
     * @var Standard
47
     */
48
    private $printer;
49
50
    public function __construct(ClassMetadata $buildingClass, ClassMetadata $builderClass, array $methods)
51
    {
52
        $this->buildingClass = $buildingClass;
53
        $this->builderClass = $builderClass;
54
        $this->factory = new BuilderFactory();
55
        $this->printer = new Standard();
56
57
        $this->namespaceNode = $this->factory->namespace($this->builderClass->getNamespace());
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->factory->namespac...rClass->getNamespace()) of type object<PhpParser\Builder\Namespace_> is incompatible with the declared type object<PhpParser\Node> of property $namespaceNode.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
58
59
        if (null !== $builderClass->getAst()) {
60
            $this->classNode = $this->builderClass->getAst();
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->builderClass->getAst() of type array is incompatible with the declared type object<PhpParser\Builder\Class_> of property $classNode.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
61
            $this->namespaceNode->addStmt($this->classNode);
0 ignored issues
show
Documentation introduced by
$this->classNode is of type array, but the function expects a object<PhpParser\Node>|object<PhpParser\Builder>.

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...
62
            return;
63
        }
64
65
        $this->initializeBuilderClass($methods);
66
67
        $this->namespaceNode->addStmt($this->classNode->getNode());
68
    }
69
70
    public function dump()
71
    {
72
        file_put_contents($this->builderClass->getFilename(), $this->display());
73
    }
74
75
    public function display()
76
    {
77
        return $this->printer->prettyPrintFile([$this->namespaceNode->getNode()]);
0 ignored issues
show
Bug introduced by
The method getNode() does not seem to exist on object<PhpParser\Node>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
78
    }
79
80
    public static function create(ClassMetadata $buildingClass, ClassMetadata $builderClass, array $methods)
81
    {
82
        return new static($buildingClass, $builderClass, $methods);
83
    }
84
85
    private function initializeBuilderClass($methods)
86
    {
87
        $this->classNode = $this->factory
88
            ->class($this->builderClass->getClass())
89
            ->extend('\\'.ReflectiveAbstractBuilder::class)
90
            ->setDocComment(sprintf(
91
'/**
92
 * Class %s
93
 *
94
 * This class is implementation of builder pattern 
95
 * for class %s. 
96
 *  
97
 * This class is autogenerated by runopencode/abstract-builder library.
98
 *
99
 * @package %s
100
 *
101
 * @see %s
102
 * @see https://en.wikipedia.org/wiki/Builder_pattern
103
 */',
104
                    $this->builderClass->getClass(), $this->buildingClass->getFqcn(), $this->builderClass->getNamespace(), $this->buildingClass->getFqcn()));
105
106
        if ($this->buildingClass->isAbstract()) {
107
            $this->classNode->makeAbstract();
108
        }
109
110
        if ($this->buildingClass->isFinal()) {
111
            $this->classNode->makeFinal();
112
        }
113
114
        /**
115
         * @var MethodMetadata $method
116
         */
117
        foreach ($methods as $method) {
118
119
            $methodFactory = $this->factory
120
                ->method($method->getName())
121
                ->makePublic();
122
123
            if ($method->getReturnType()) {
124
                $methodFactory->setReturnType($method->getReturnType() instanceof ClassMetadata ? (string) $method->getReturnType() : $method->getReturnType());
125
            }
126
127
            foreach ($method->getParameters() as $parameter) {
128
                $parameterFactory = $this->factory
129
                    ->param($parameter->getName());
130
131
                if ($parameter->getType()) {
132
                    $parameterFactory->setTypeHint($parameter->getType());
133
                }
134
135
                $methodFactory->addParam($parameterFactory->getNode());
136
            }
137
138
            $this->classNode->addStmt($methodFactory->getNode());
139
        }
140
141
        $getObjectFqcnMethod = $this->factory->method('getObjectFqcn')
142
            ->makeProtected()
143
            ->addStmt(new Node\Stmt\Return_(new Node\Scalar\String_($this->buildingClass->getFqcn())))
144
            ->setDocComment(sprintf(
145
'
146
/**
147
 * {@inheritdoc}
148
 */'
149
            ));
150
151
        $this->classNode->addStmt($getObjectFqcnMethod->getNode());
152
    }
153
}
154