ClassInfo   A
last analyzed

Complexity

Total Complexity 15

Size/Duplication

Total Lines 116
Duplicated Lines 0 %

Test Coverage

Coverage 80%

Importance

Changes 0
Metric Value
wmc 15
eloc 44
c 0
b 0
f 0
dl 0
loc 116
ccs 40
cts 50
cp 0.8
rs 10

10 Methods

Rating   Name   Duplication   Size   Complexity  
A toString() 0 9 1
A from() 0 7 2
A getModuleNamespace() 0 4 1
A getCacheKey() 0 4 1
A fromString() 0 34 4
A fromObject() 0 5 1
A getResolvableType() 0 4 1
A __construct() 0 6 1
A getModuleName() 0 4 1
A normalizeFilename() 0 10 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Gacela\Framework\ClassResolver;
6
7
use Override;
8
9
use function array_slice;
10
use function count;
11
use function is_object;
12
use function is_string;
13
use function sprintf;
14
15
final class ClassInfo implements ClassInfoInterface
16
{
17
    public const MODULE_NAME_ANONYMOUS = 'module-name@anonymous';
18
19
    /** @var array<string,array<string,self>> */
20 49
    private static array $callerClassCache;
21
22
    public function __construct(
23
        private readonly string $callerModuleNamespace,
24
        private readonly string $callerModuleName,
25
        private readonly string $cacheKey,
26 49
        private readonly string $resolvableType = '',
27
    ) {
28
    }
29
30
    /**
31 82
     * @param object|class-string $caller
0 ignored issues
show
Documentation Bug introduced by
The doc comment object|class-string at position 2 could not be parsed: Unknown type name 'class-string' at position 2 in object|class-string.
Loading history...
32
     */
33 82
    public static function from(object|string $caller, string $resolvableType = ''): self
34 37
    {
35
        if (is_object($caller)) {
36
            return self::fromObject($caller, $resolvableType);
37 73
        }
38
39
        return self::fromString($caller, $resolvableType);
40 72
    }
41
42 72
    #[Override]
43
    public function getModuleNamespace(): string
44
    {
45 71
        return $this->callerModuleNamespace;
46
    }
47 71
48
    #[Override]
49
    public function getModuleName(): string
50 81
    {
51
        return $this->callerModuleName;
52 81
    }
53
54
    #[Override]
55
    public function getCacheKey(): string
56
    {
57
        return $this->cacheKey;
58
    }
59
60
    #[Override]
61
    public function getResolvableType(): string
62
    {
63
        return $this->resolvableType;
64
    }
65
66
    #[Override]
67
    public function toString(): string
68
    {
69
        return sprintf(
70
            '{callerModuleNamespace:"%s", callerModuleName:"%s", resolvableType:"%s", cacheKey:"%s"}',
71 37
            $this->callerModuleNamespace,
72
            $this->callerModuleName,
73 37
            $this->resolvableType,
74
            $this->cacheKey,
75 37
        );
76
    }
77
78 82
    private static function fromObject(object $callerObject, string $resolvableType): self
79
    {
80 82
        $callerClass = $callerObject::class;
81 49
82
        return self::fromString($callerClass, $resolvableType);
83
    }
84 44
85 44
    private static function fromString(string $callerClass, string $resolvableType): self
86 44
    {
87 44
        if (isset(self::$callerClassCache[$callerClass][$resolvableType])) {
88
            return self::$callerClassCache[$callerClass][$resolvableType];
89 44
        }
90 4
91 4
        /** @var list<string> $callerClassParts */
92 4
        $callerClassParts = explode('\\', ltrim($callerClass, '\\'));
93 4
        $lastCallerClassPart = end($callerClassParts);
94
        $filepath = is_string($lastCallerClassPart) ? $lastCallerClassPart : '';
95
        $filename = self::normalizeFilename($filepath);
96 44
97
        if (str_contains($callerClass, 'anonymous')) {
98 44
            $callerClassParts = [
99
                self::MODULE_NAME_ANONYMOUS . '\\' . $filename,
100
                $filepath,
101
            ];
102
        }
103
104 44
        $callerFullNamespace = implode('\\', array_slice($callerClassParts, 0, count($callerClassParts) - 1));
105 44
106
        $callerModuleNamespace = substr($callerFullNamespace, 0, (int)strrpos($callerFullNamespace, '\\'));
107 44
        /**
108 44
         * @psalm-suppress InvalidArrayOffset
109
         *
110 44
         * @var string $callerModuleName
111
         */
112
        $callerModuleName = $callerClassParts[count($callerClassParts) - 2] ?? '';
113 44
        $cacheKey = GlobalKey::fromClassName(sprintf('\\%s\\%s', $callerFullNamespace, $resolvableType));
114
115 44
        $self = new self($callerModuleNamespace, $callerModuleName, $cacheKey, $resolvableType);
116 44
        self::$callerClassCache[$callerClass][$resolvableType] = $self;
117
118 44
        return $self;
119 41
    }
120
121
    private static function normalizeFilename(string $filepath): string
122 4
    {
123
        $filename = basename($filepath);
124
        $filename = substr($filename, 0, (int)strpos($filename, ':'));
125
126
        if (false === ($pos = strpos($filename, '.'))) {
127
            return $filename;
128
        }
129
130
        return substr($filename, 0, $pos);
131
    }
132
}
133