Completed
Pull Request — 2.x (#349)
by Alexander
02:20
created

InterceptedConstructorGenerator::__construct()   C

Complexity

Conditions 7
Paths 10

Size

Total Lines 27
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 7

Importance

Changes 0
Metric Value
dl 0
loc 27
ccs 17
cts 17
cp 1
rs 6.7272
c 0
b 0
f 0
cc 7
eloc 21
nc 10
nop 4
crap 7
1
<?php
2
declare(strict_types=1);
3
/*
4
 * Go! AOP framework
5
 *
6
 * @copyright Copyright 2018, Lisachenko Alexander <[email protected]>
7
 *
8
 * This source file is subject to the license that is bundled
9
 * with this source code in the file LICENSE.
10
 */
11
12
namespace Go\Proxy\Part;
13
14
use ReflectionMethod;
15
use Zend\Code\Generator\MethodGenerator;
16
use function count;
17
18
/**
19
 * Prepares the definition of intercepted constructor
20
 */
21
final class InterceptedConstructorGenerator extends MethodGenerator
22
{
23
24
    /**
25
     * Constructor generator
26
     *
27
     * @var MethodGenerator
28
     */
29
    private $generatedConstructor;
30
31
    /**
32
     * InterceptedConstructor
33
     *
34
     * @param array            $interceptedProperties List of intercepted properties for the class
35
     * @param ReflectionMethod $constructor           Instance of original constructor or null
36
     * @param MethodGenerator  $generatedConstructor  Constructor body generator (if present)
37
     * @param bool             $useTypeWidening       Should generator use parameter widening for PHP>=7.2
38
     *
39
     * @throws \LogicException if constructor is private
40
     */
41 6
    public function __construct(
42
        array $interceptedProperties,
43
        ReflectionMethod $constructor = null,
44
        MethodGenerator $generatedConstructor = null,
45
        bool $useTypeWidening = false
46
    ) {
47 6
        $constructorBody = count($interceptedProperties) > 0 ? $this->getConstructorBody($interceptedProperties) : '';
48 6
        if ($constructor !== null && $constructor->isPrivate()) {
49 1
            throw new \LogicException(
50 1
                "Constructor in the class {$constructor->class} is declared as private. " .
51 1
                "Properties could not be intercepted."
52
            );
53
        }
54 5
        if ($constructor !== null) {
55 3
            if ($generatedConstructor === null) {
56 3
                $callArguments        = new FunctionCallArgumentListGenerator($constructor);
57 3
                $splatPrefix          = $constructor->getNumberOfParameters() > 0 ? '...' : '';
58 3
                $parentCallBody       = 'parent::__construct(' . $splatPrefix . $callArguments->generate() . ');';
59 3
                $generatedConstructor = new InterceptedMethodGenerator($constructor, $parentCallBody, $useTypeWidening);
60
            }
61 3
            $constructorBody .= PHP_EOL . $generatedConstructor->getBody();
62 3
            $generatedConstructor->setBody($constructorBody);
63
        } else {
64 2
            $generatedConstructor = new MethodGenerator('__construct', [], [], $constructorBody);
0 ignored issues
show
Documentation introduced by
array() is of type array, but the function expects a integer.

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...
65
        }
66 5
        $this->generatedConstructor = $generatedConstructor;
67 5
    }
68
69
    /**
70
     * @inheritdoc
71
     */
72 5
    public function generate()
73
    {
74 5
        return $this->generatedConstructor->generate();
75
    }
76
77
    /**
78
     * Returns constructor code
79
     *
80
     * @param array $interceptedProperties List of properties to intercept
81
     *
82
     * @return string
83
     */
84 2
    private function getConstructorBody(array $interceptedProperties): string
85
    {
86 2
        $assocProperties = [];
87 2
        $listProperties  = [];
88 2
        foreach ($interceptedProperties as $propertyName) {
89 2
            $assocProperties[] = "    '{$propertyName}' => &\$this->{$propertyName}";
90 2
            $listProperties[]  = "    \$this->{$propertyName}";
91
        }
92
        $lines = [
93 2
            '$this->__properties = [',
94 2
            implode(',' . PHP_EOL, $assocProperties),
95 2
            '];',
96 2
            'unset(',
97 2
            implode(',' . PHP_EOL, $listProperties),
98 2
            ');'
99
        ];
100
101 2
        return implode(PHP_EOL, $lines);
102
    }
103
}
104