Passed
Push — master ( fedbc6...da3a15 )
by Satoshi
02:47
created

FullyQualifiedStructuralElementName::formatName()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 1
nc 2
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
declare(strict_types=1);
3
4
namespace DependencyAnalyzer\DependencyGraph;
5
6
use DependencyAnalyzer\DependencyGraph\FullyQualifiedStructuralElementName\Base;
7
use DependencyAnalyzer\DependencyGraph\FullyQualifiedStructuralElementName\Class_;
8
use DependencyAnalyzer\DependencyGraph\FullyQualifiedStructuralElementName\ClassConstant;
9
use DependencyAnalyzer\DependencyGraph\FullyQualifiedStructuralElementName\Constant;
10
use DependencyAnalyzer\DependencyGraph\FullyQualifiedStructuralElementName\Function_;
11
use DependencyAnalyzer\DependencyGraph\FullyQualifiedStructuralElementName\Interface_;
12
use DependencyAnalyzer\DependencyGraph\FullyQualifiedStructuralElementName\Method;
13
use DependencyAnalyzer\DependencyGraph\FullyQualifiedStructuralElementName\Namespace_;
14
use DependencyAnalyzer\DependencyGraph\FullyQualifiedStructuralElementName\Property;
15
use DependencyAnalyzer\DependencyGraph\FullyQualifiedStructuralElementName\Trait_;
16
use DependencyAnalyzer\Exceptions\InvalidFullyQualifiedStructureElementNameException;
17
18
class FullyQualifiedStructuralElementName
19
{
20
    const TYPE_NAMESPACE = 'namespace';
21
    const TYPE_CLASS = 'class';
22
    const TYPE_METHOD = 'method';
23
    const TYPE_PROPERTY = 'property';
24
    const TYPE_CLASS_CONSTANT = 'class_constant';
25
    const TYPE_INTERFACE = 'interface';
26
    const TYPE_TRAIT = 'trait';
27
    const TYPE_FUNCTION = 'function';
28
    const TYPE_CONSTANT = 'constant';
29
30
    public static function createFromString(string $element): Base
31
    {
32
        if (self::isNamespaceElement($element)) {
33
            return new Namespace_($element);
34
        } elseif (self::isMethodElement($element)) {
35
            return new Method($element);
36
        } elseif (self::isPropertyElement($element)) {
37
            return new Property($element);
38
        } elseif (self::isClassConstantElement($element)) {
39
            return new ClassConstant($element);
40
        } elseif (self::isFunctionElement($element)) {
41
            return new Function_($element);
42
        } elseif (self::isFullyQualifiedClassElement($element)) {
43
            return new Class_($element);
44
        }
45
46
        throw new InvalidFullyQualifiedStructureElementNameException($element);
47
    }
48
49
    protected static function isNamespaceElement(string $element): bool
50
    {
51
        if ($element === '\\') {
52
            return true;
53
        }
54
55
        // TODO: This is my original definition...
56
        return substr($element, -1) === '\\' &&
57
            self::isFullyQualifiedClassElement(substr($element, 0, -1));
58
    }
59
60
    protected static function isMethodElement(string $element): bool
61
    {
62
        if (strpos($element, '::') === false) {
63
            return false;
64
        }
65
66
        list($fqcn, $method) = explode('::', $element, 2);
67
68
        return self::isFullyQualifiedClassElement($fqcn) &&
69
            substr($method, -2) === '()' &&
70
            self::isName(substr($method, 0, -2));
71
    }
72
73
    protected static function isPropertyElement(string $element): bool
74
    {
75
        if (strpos($element, '::') === false) {
76
            return false;
77
        }
78
79
        list($fqcn, $property) = explode('::', $element, 2);
80
81
        return self::isFullyQualifiedClassElement($fqcn) &&
82
            substr($property, 0, 1) === '$' &&
83
            self::isName(substr($property, 1));
84
    }
85
86
    protected static function isClassConstantElement(string $element): bool
87
    {
88
        if (strpos($element, '::') === false) {
89
            return false;
90
        }
91
92
        list($fqcn, $constant) = explode('::', $element, 2);
93
94
        return self::isFullyQualifiedClassElement($fqcn) &&
95
            self::isName($constant);
96
    }
97
98
    protected static function isFunctionElement(string $element): bool
99
    {
100
        return substr($element, -2) === '()' &&
101
            self::isFullyQualifiedClassElement(substr($element, 0, -2));
102
    }
103
104
    protected static function isFullyQualifiedClassElement(string $element): bool
105
    {
106
        if (substr($element, 0, 1) !== '\\') {
107
            return false;
108
        }
109
110
        $names = explode('\\', $element);
111
        if (array_shift($names) !== '') {
112
            return false;
113
        } elseif (count($names) <= 0) {
114
            return false;
115
        }
116
        foreach ($names as $name) {
117
            if (!self::isName($name)) {
118
                return false;
119
            }
120
        }
121
122
        return true;
123
    }
124
125
    protected static function isName(string $element): bool
126
    {
127
        return preg_match('/^[a-zA-Z\_][0-9a-zA-Z\_]+$/', $element) === 1;
128
    }
129
130
    public static function createNamespace(string $namespaceName): Base
131
    {
132
        return new Namespace_(self::formatName($namespaceName));
133
    }
134
135
    public static function createClass(string $className): Class_
136
    {
137
        return new Class_(self::formatName($className));
138
    }
139
140
    public static function createMethod(string $className, string $methodName): Method
141
    {
142
        $className = self::formatName($className);
143
        return new Method("{$className}::{$methodName}()");
144
    }
145
146
    public static function createProperty(string $className, string $propertyName): Property
147
    {
148
        $className = self::formatName($className);
149
        return new Property("{$className}::\${$propertyName}");
150
    }
151
152
    public static function createClassConstant(string $className, string $constantName): ClassConstant
153
    {
154
        $className = self::formatName($className);
155
        return new ClassConstant("{$className}::{$constantName}");
156
    }
157
158
    public static function createInterface(string $interfaceName): Interface_
159
    {
160
        $interfaceName = self::formatName($interfaceName);
161
        return new Interface_($interfaceName);
162
    }
163
164
    public static function createTrait(string $traitName): Trait_
165
    {
166
        $traitName = self::formatName($traitName);
167
        return new Trait_($traitName);
168
    }
169
170
    public static function createFunction(string $functionName): Function_
171
    {
172
        $functionName = self::formatName($functionName);
173
        return new Function_("{$functionName}()");
174
    }
175
176
    public static function createConstant(string $constantName): Constant
177
    {
178
        $constantName = self::formatName($constantName);
179
        return new Constant("{$constantName}");
180
    }
181
182
    protected static function formatName(string $className): string
183
    {
184
        return substr($className, 0, 1) === '\\' ? $className : "\\{$className}";
185
    }
186
}
187