Passed
Pull Request — master (#39)
by
unknown
02:08
created

ProxyManager::createObjectProxy()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 26
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 4

Importance

Changes 0
Metric Value
cc 4
eloc 16
c 0
b 0
f 0
nc 5
nop 3
dl 0
loc 26
ccs 16
cts 16
cp 1
crap 4
rs 9.7333
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Proxy;
6
7
use Yiisoft\Proxy\Config\ClassConfig;
8
9
final class ProxyManager
10
{
11
    private ClassRenderer $classRenderer;
12
13
    private ClassConfigFactory $classConfigFactory;
14
15
    private ?ClassCache $classCache;
16
17
    public const PROXY_SUFFIX = 'Proxy';
18
19 8
    public function __construct(string $cachePath = null)
20
    {
21 8
        $this->classCache = $cachePath ? new ClassCache($cachePath) : null;
22 8
        $this->classRenderer = new ClassRenderer();
23 8
        $this->classConfigFactory = new ClassConfigFactory();
24
    }
25
26 8
    public function createObjectProxy(
27
        string $baseStructure,
28
        string $parentProxyClass,
29
        array $constructorArguments
30
    ): ?object {
31 8
        $className = $baseStructure . self::PROXY_SUFFIX;
32 8
        $shortClassName = $this->getProxyClassName($className);
33
34 8
        if (class_exists($shortClassName)) {
35 5
            return new $shortClassName(...$constructorArguments);
36
        }
37
38 3
        $classDeclaration = $this->classCache?->get($className, $parentProxyClass);
39 3
        if (!$classDeclaration) {
40 3
            $classConfig = $this->classConfigFactory->getClassConfig($baseStructure);
41 3
            $classConfig = $this->generateProxyClassConfig($classConfig, $parentProxyClass);
42 3
            $classDeclaration = $this->classRenderer->render($classConfig);
43 3
            $this->classCache?->set($baseStructure, $parentProxyClass, $classDeclaration);
44
        }
45 3
        if (!$this->classCache) {
46 1
            eval(str_replace('<?php', '', $classDeclaration));
0 ignored issues
show
introduced by
The use of eval() is discouraged.
Loading history...
47
        } else {
48 2
            $path = $this->classCache->getClassPath($baseStructure, $parentProxyClass);
49 2
            require $path;
50
        }
51 3
        return new $shortClassName(...$constructorArguments);
52
    }
53
54 3
    private function generateProxyClassConfig(
55
        ClassConfig $classConfig,
56
        string $parentProxyClass
57
    ): ClassConfig {
58 3
        if ($classConfig->isInterface) {
59 2
            $classConfig->isInterface = false;
60 2
            $classConfig->interfaces = [$classConfig->name];
61
        }
62
63 3
        $classConfig->parent = $parentProxyClass;
64 3
        $classConfig->name .= self::PROXY_SUFFIX;
65 3
        $classConfig->shortName = $this->getProxyClassName($classConfig->name);
66
67 3
        foreach ($classConfig->methods as $methodIndex => $method) {
68 3
            foreach ($method->modifiers as $index => $modifier) {
69 3
                if ($modifier === 'abstract') {
70 2
                    unset($classConfig->methods[$methodIndex]->modifiers[$index]);
71
                }
72
            }
73
        }
74
75 3
        return $classConfig;
76
    }
77
78 8
    private function getProxyClassName(string $fullClassName)
79
    {
80 8
        return str_replace('\\', '_', $fullClassName);
81
    }
82
}
83