Completed
Push — master ( f1e5e5...9f8061 )
by Marco
07:19
created

Constructor::generateOriginalConstructorCall()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 17
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 17
ccs 10
cts 10
cp 1
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 13
nc 1
nop 2
crap 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace ProxyManager\ProxyGenerator\ValueHolder\MethodGenerator;
6
7
use ProxyManager\Generator\MethodGenerator;
8
use ProxyManager\ProxyGenerator\Util\Properties;
9
use ProxyManager\ProxyGenerator\Util\UnsetPropertiesGenerator;
10
use ReflectionClass;
11
use Zend\Code\Generator\PropertyGenerator;
12
use Zend\Code\Reflection\MethodReflection;
13
use Zend\Code\Reflection\ParameterReflection;
14
15
/**
16
 * The `__construct` implementation for lazy loading proxies
17
 *
18
 * @author Marco Pivetta <[email protected]>
19
 * @license MIT
20
 */
21
class Constructor extends MethodGenerator
22
{
23
    /**
24
     * @throws \Zend\Code\Generator\Exception\InvalidArgumentException
25
     */
26 4
    public static function generateMethod(ReflectionClass $originalClass, PropertyGenerator $valueHolder) : self
27
    {
28 4
        $originalConstructor = self::getConstructor($originalClass);
29
30
        /* @var $constructor self */
31 4
        $constructor = $originalConstructor
32 1
            ? self::fromReflectionWithoutBodyAndDocBlock($originalConstructor)
33 4
            : new self('__construct');
34
35 4
        $constructor->setBody(
36
            'static $reflection;' . "\n\n"
37 4
            . 'if (! $this->' . $valueHolder->getName() . ') {' . "\n"
38 4
            . '    $reflection = $reflection ?: new \ReflectionClass('
39 4
            . var_export($originalClass->getName(), true)
40 4
            . ");\n"
41 4
            . '    $this->' . $valueHolder->getName() . ' = $reflection->newInstanceWithoutConstructor();' . "\n"
42 4
            . UnsetPropertiesGenerator::generateSnippet(Properties::fromReflectionClass($originalClass), 'this')
43 4
            . '}'
44 4
            . ($originalConstructor ? self::generateOriginalConstructorCall($originalConstructor, $valueHolder) : '')
45
        );
46
47 4
        return $constructor;
48
    }
49
50 1
    private static function generateOriginalConstructorCall(
51
        MethodReflection $originalConstructor,
52
        PropertyGenerator $valueHolder
53
    ) : string {
54
        return "\n\n"
55 1
            . '$this->' . $valueHolder->getName() . '->' . $originalConstructor->getName() . '('
56 1
            . implode(
57 1
                ', ',
58 1
                array_map(
59 1
                    function (ParameterReflection $parameter) : string {
60 1
                        return ($parameter->isVariadic() ? '...' : '') . '$' . $parameter->getName();
61 1
                    },
62 1
                    $originalConstructor->getParameters()
63
                )
64
            )
65 1
            . ');';
66
    }
67
68
    /**
69
     * @param ReflectionClass $class
70
     *
71
     * @return MethodReflection|null
72
     */
73 4
    private static function getConstructor(ReflectionClass $class)
74
    {
75 4
        $constructors = array_map(
76 4
            function (\ReflectionMethod $method) : MethodReflection {
77 1
                return new MethodReflection(
78 1
                    $method->getDeclaringClass()->getName(),
79 1
                    $method->getName()
80
                );
81 4
            },
82 4
            array_filter(
83 4
                $class->getMethods(),
84 4
                function (\ReflectionMethod $method) : bool {
85 1
                    return $method->isConstructor();
86 4
                }
87
            )
88
        );
89
90
        return reset($constructors) ?: null;
91
    }
92
}
93