LazyLoadingGhostGenerator   A
last analyzed

Complexity

Total Complexity 2

Size/Duplication

Total Lines 107
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 18

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 2
lcom 0
cbo 18
dl 0
loc 107
ccs 66
cts 66
cp 1
rs 10
c 0
b 0
f 0

2 Methods

Rating   Name   Duplication   Size   Complexity  
B generate() 0 73 1
A getAbstractProxiedMethods() 0 15 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace ProxyManager\ProxyGenerator;
6
7
use InvalidArgumentException;
8
use Laminas\Code\Generator\ClassGenerator;
9
use Laminas\Code\Generator\MethodGenerator;
10
use Laminas\Code\Reflection\MethodReflection;
11
use ProxyManager\Exception\InvalidProxiedClassException;
12
use ProxyManager\Generator\MethodGenerator as ProxyManagerMethodGenerator;
13
use ProxyManager\Generator\Util\ClassGeneratorUtils;
14
use ProxyManager\Proxy\GhostObjectInterface;
15
use ProxyManager\ProxyGenerator\Assertion\CanProxyAssertion;
16
use ProxyManager\ProxyGenerator\LazyLoading\MethodGenerator\StaticProxyConstructor;
17
use ProxyManager\ProxyGenerator\LazyLoadingGhost\MethodGenerator\CallInitializer;
18
use ProxyManager\ProxyGenerator\LazyLoadingGhost\MethodGenerator\GetProxyInitializer;
19
use ProxyManager\ProxyGenerator\LazyLoadingGhost\MethodGenerator\InitializeProxy;
20
use ProxyManager\ProxyGenerator\LazyLoadingGhost\MethodGenerator\IsProxyInitialized;
21
use ProxyManager\ProxyGenerator\LazyLoadingGhost\MethodGenerator\MagicClone;
22
use ProxyManager\ProxyGenerator\LazyLoadingGhost\MethodGenerator\MagicGet;
23
use ProxyManager\ProxyGenerator\LazyLoadingGhost\MethodGenerator\MagicIsset;
24
use ProxyManager\ProxyGenerator\LazyLoadingGhost\MethodGenerator\MagicSet;
25
use ProxyManager\ProxyGenerator\LazyLoadingGhost\MethodGenerator\MagicSleep;
26
use ProxyManager\ProxyGenerator\LazyLoadingGhost\MethodGenerator\MagicUnset;
27
use ProxyManager\ProxyGenerator\LazyLoadingGhost\MethodGenerator\SetProxyInitializer;
28
use ProxyManager\ProxyGenerator\LazyLoadingGhost\PropertyGenerator\InitializationTracker;
29
use ProxyManager\ProxyGenerator\LazyLoadingGhost\PropertyGenerator\InitializerProperty;
30
use ProxyManager\ProxyGenerator\LazyLoadingGhost\PropertyGenerator\PrivatePropertiesMap;
31
use ProxyManager\ProxyGenerator\LazyLoadingGhost\PropertyGenerator\ProtectedPropertiesMap;
32
use ProxyManager\ProxyGenerator\PropertyGenerator\PublicPropertiesMap;
33
use ProxyManager\ProxyGenerator\Util\Properties;
34
use ProxyManager\ProxyGenerator\Util\ProxiedMethodsFilter;
35
use ReflectionClass;
36
use ReflectionMethod;
37
use function array_map;
38
use function array_merge;
39
40
/**
41
 * Generator for proxies implementing {@see \ProxyManager\Proxy\GhostObjectInterface}
42
 *
43
 * {@inheritDoc}
44
 */
45
class LazyLoadingGhostGenerator implements ProxyGeneratorInterface
46
{
47
    /**
48
     * {@inheritDoc}
49
     *
50
     * @return void
51
     *
52
     * @throws InvalidProxiedClassException
53
     * @throws InvalidArgumentException
54
     *
55 14
     * @psalm-param array{skippedProperties?: array<int, string>} $proxyOptions
56
     */
57 14
    public function generate(ReflectionClass $originalClass, ClassGenerator $classGenerator, array $proxyOptions = [])
58
    {
59 8
        CanProxyAssertion::assertClassCanBeProxied($originalClass, false);
60 8
61
        $filteredProperties = Properties::fromReflectionClass($originalClass)
62 8
            ->filter($proxyOptions['skippedProperties'] ?? []);
63 8
64 8
        $publicProperties    = new PublicPropertiesMap($filteredProperties);
65
        $privateProperties   = new PrivatePropertiesMap($filteredProperties);
66 8
        $protectedProperties = new ProtectedPropertiesMap($filteredProperties);
67 8
68 8
        $classGenerator->setExtendedClass($originalClass->getName());
69 8
        $classGenerator->setImplementedInterfaces([GhostObjectInterface::class]);
70 8
        $classGenerator->addPropertyFromGenerator($initializer           = new InitializerProperty());
71 8
        $classGenerator->addPropertyFromGenerator($initializationTracker = new InitializationTracker());
72 8
        $classGenerator->addPropertyFromGenerator($publicProperties);
73
        $classGenerator->addPropertyFromGenerator($privateProperties);
74 8
        $classGenerator->addPropertyFromGenerator($protectedProperties);
75
76 8
        $init = new CallInitializer($initializer, $initializationTracker, $filteredProperties);
77
78 8
        array_map(
79 8
            static function (MethodGenerator $generatedMethod) use ($originalClass, $classGenerator) : void {
80 8
                ClassGeneratorUtils::addMethodIfNotFinal($originalClass, $classGenerator, $generatedMethod);
81 8
            },
82
            array_merge(
83 8
                $this->getAbstractProxiedMethods($originalClass),
84 8
                [
85 8
                    $init,
86 8
                    new StaticProxyConstructor($initializer, $filteredProperties),
87 8
                    new MagicGet(
88 8
                        $originalClass,
89 8
                        $initializer,
90 8
                        $init,
91 8
                        $publicProperties,
92 8
                        $protectedProperties,
93
                        $privateProperties,
94 8
                        $initializationTracker
95 8
                    ),
96 8
                    new MagicSet(
97 8
                        $originalClass,
98 8
                        $initializer,
99 8
                        $init,
100 8
                        $publicProperties,
101
                        $protectedProperties,
102 8
                        $privateProperties
103 8
                    ),
104 8
                    new MagicIsset(
105 8
                        $originalClass,
106 8
                        $initializer,
107 8
                        $init,
108 8
                        $publicProperties,
109
                        $protectedProperties,
110 8
                        $privateProperties
111 8
                    ),
112 8
                    new MagicUnset(
113 8
                        $originalClass,
114 8
                        $initializer,
115 8
                        $init,
116 8
                        $publicProperties,
117
                        $protectedProperties,
118 8
                        $privateProperties
119 8
                    ),
120 8
                    new MagicClone($originalClass, $initializer, $init),
121 8
                    new MagicSleep($originalClass, $initializer, $init),
122 8
                    new SetProxyInitializer($initializer),
123 8
                    new GetProxyInitializer($initializer),
124
                    new InitializeProxy($initializer, $init),
125
                    new IsProxyInitialized($initializer),
126
                ]
127 8
            )
128
        );
129
    }
130
131
    /**
132
     * Retrieves all abstract methods to be proxied
133
     *
134
     * @return MethodGenerator[]
135 8
     */
136
    private function getAbstractProxiedMethods(ReflectionClass $originalClass) : array
137 8
    {
138
        return array_map(
139 2
            static function (ReflectionMethod $method) : ProxyManagerMethodGenerator {
140 2
                $generated = ProxyManagerMethodGenerator::fromReflectionWithoutBodyAndDocBlock(
141
                    new MethodReflection($method->getDeclaringClass()->getName(), $method->getName())
142
                );
143 2
144
                $generated->setAbstract(false);
145 2
146 8
                return $generated;
147 8
            },
148
            ProxiedMethodsFilter::getAbstractProxiedMethods($originalClass)
149
        );
150
    }
151
}
152