Completed
Push — master ( ce73d9...ed5962 )
by Nikola
03:35
created

ClassBuilder::initializeBuilderClass()   B

Complexity

Conditions 4
Paths 8

Size

Total Lines 53
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
dl 0
loc 53
ccs 0
cts 43
cp 0
rs 8.9849
c 0
b 0
f 0
cc 4
eloc 22
nc 8
nop 1
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
 * 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
            $this->classNode->addStmt($methodFactory->getNode());
124
        }
125
126
        $getObjectFqcnMethod = $this->factory->method('getObjectFqcn')
127
            ->makeProtected()
128
            ->addStmt(new Node\Stmt\Return_(new Node\Scalar\String_($this->buildingClass->getFqcn())))
129
            ->setDocComment(sprintf(
130
'
131
/**
132
 * {@inheritdoc}
133
 */'
134
            ));
135
136
        $this->classNode->addStmt($getObjectFqcnMethod->getNode());
137
    }
138
}
139