generateUnsetClassPrivatePropertiesBlock()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 16
ccs 8
cts 8
cp 1
rs 9.7333
c 0
b 0
f 0
cc 1
nc 1
nop 3
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace ProxyManager\ProxyGenerator\Util;
6
7
use ReflectionClass;
8
use ReflectionProperty;
9
use function array_map;
10
use function implode;
11
use function reset;
12
use function sprintf;
13
use function var_export;
14
15
/**
16
 * Generates code necessary to unset all the given properties from a particular given instance string name
17
 */
18
final class UnsetPropertiesGenerator
19
{
20
    private const CLOSURE_TEMPLATE = <<<'PHP'
21
\Closure::bind(function (\%s $instance) {
22
    %s
23
}, $%s, %s)->__invoke($%s);
24
PHP;
25
26 4
    public static function generateSnippet(Properties $properties, string $instanceName) : string
27
    {
28 4
        $unsettableProperties = $properties->onlyPropertiesThatCanBeUnset();
29 4
30
        return self::generateUnsetAccessiblePropertiesCode($unsettableProperties, $instanceName)
31
            . self::generateUnsetPrivatePropertiesCode($unsettableProperties, $instanceName);
32 4
    }
33
34 4
    private static function generateUnsetAccessiblePropertiesCode(Properties $properties, string $instanceName) : string
35
    {
36 4
        $accessibleProperties = $properties->getAccessibleProperties();
37 2
38
        if (! $accessibleProperties) {
39
            return '';
40 2
        }
41
42
        return self::generateUnsetStatement($accessibleProperties, $instanceName) . "\n\n";
43 4
    }
44
45 4
    private static function generateUnsetPrivatePropertiesCode(Properties $properties, string $instanceName) : string
46
    {
47 4
        $groups = $properties->getGroupedPrivateProperties();
48 1
49
        if (! $groups) {
50
            return '';
51 3
        }
52
53
        $unsetClosureCalls = [];
54 3
55
        foreach ($groups as $privateProperties) {
56 3
            /** @var ReflectionProperty $firstProperty */
57
            $firstProperty = reset($privateProperties);
58 3
59 3
            $unsetClosureCalls[] = self::generateUnsetClassPrivatePropertiesBlock(
60 3
                $firstProperty->getDeclaringClass(),
61 3
                $privateProperties,
62
                $instanceName
63
            );
64
        }
65 3
66
        return implode("\n\n", $unsetClosureCalls) . "\n\n";
67
    }
68
69 3
    /** @param array<string, ReflectionProperty> $properties */
70
    private static function generateUnsetClassPrivatePropertiesBlock(
71
        ReflectionClass $declaringClass,
72
        array $properties,
73
        string $instanceName
74 3
    ) : string {
75
        $declaringClassName = $declaringClass->getName();
76 3
77 3
        return sprintf(
78 3
            self::CLOSURE_TEMPLATE,
79 3
            $declaringClassName,
80 3
            self::generateUnsetStatement($properties, 'instance'),
81 3
            $instanceName,
82 3
            var_export($declaringClassName, true),
83
            $instanceName
84
        );
85
    }
86
87 3
    /** @param array<string, ReflectionProperty> $properties */
88
    private static function generateUnsetStatement(array $properties, string $instanceName) : string
89
    {
90 3
        return 'unset('
91 3
            . implode(
92 3
                ', ',
93
                array_map(
94 3
                    static function (ReflectionProperty $property) use ($instanceName) : string {
95 3
                        return '$' . $instanceName . '->' . $property->getName();
96 3
                    },
97
                    $properties
98
                )
99 3
            )
100
            . ');';
101
    }
102
}
103