1: <?php
2: namespace Pharborist\Namespaces;
3:
4: use Pharborist\Constants\ConstantNode;
5: use Pharborist\Filter;
6: use Pharborist\Functions\FunctionCallNode;
7: use Pharborist\ParentNode;
8: use Pharborist\Token;
9: use Pharborist\TokenNode;
10:
11: 12: 13: 14: 15: 16: 17: 18:
19: class NameNode extends ParentNode {
20: 21: 22: 23: 24: 25:
26: public static function create($name) {
27: $parts = explode('\\', $name);
28: $name_node = new NameNode();
29: foreach ($parts as $i => $part) {
30: $part = trim($part);
31: if ($i > 0) {
32: $name_node->append(Token::namespaceSeparator());
33: }
34: if ($part !== '') {
35: $name_node->append(Token::identifier($part));
36: }
37: }
38: return $name_node;
39: }
40:
41: 42: 43: 44: 45: 46:
47: public function getNamespace() {
48: return $this->closest(Filter::isInstanceOf('\Pharborist\Namespaces\NamespaceNode'));
49: }
50:
51: 52: 53:
54: public function getParentPath() {
55: if ($this->parent instanceof NamespaceNode) {
56: return '\\';
57: }
58: if ($this->isAbsolute()) {
59: return '\\';
60: }
61:
62: $namespace = $this->getNamespace();
63: if (!$namespace) {
64: return '\\';
65: }
66: else {
67: $name = $namespace->getName();
68: if (!$name) {
69: return '\\';
70: }
71: return '\\' . $name->getPath() . '\\';
72: }
73: }
74:
75: 76: 77: 78:
79: public function getPathInfo() {
80:
81: $first = $this->firstChild();
82: $absolute = $first->getType() === T_NS_SEPARATOR;
83: $relative = $first->getType() === T_NAMESPACE;
84: $parts = $this->getParts();
85: return [
86: 'absolute' => $absolute,
87: 'relative' => $relative,
88: 'qualified' => !$absolute && count($parts) > 1,
89: 'unqualified' => !$absolute && count($parts) === 1,
90: 'parts' => $parts,
91: ];
92: }
93:
94: 95: 96: 97: 98:
99: public function isAbsolute() {
100:
101: $first = $this->firstChild();
102: return $first->getType() === T_NS_SEPARATOR;
103: }
104:
105: 106: 107: 108: 109:
110: public function isRelative() {
111:
112: $first = $this->firstChild();
113: return $first->getType() === T_NAMESPACE;
114: }
115:
116: 117: 118: 119: 120:
121: public function isUnqualified() {
122: $absolute = $this->isAbsolute();
123: $parts = $this->getParts();
124: return !$absolute && count($parts) === 1;
125: }
126:
127: 128: 129: 130: 131:
132: public function isQualified() {
133: $absolute = $this->isAbsolute();
134: $parts = $this->getParts();
135: return !$absolute && count($parts) > 1;
136: }
137:
138: 139: 140:
141: public function getParts() {
142: $parts = [];
143:
144: $child = $this->head;
145: while ($child) {
146: $type = $child->getType();
147: if ($type === T_NAMESPACE || $type === T_STRING) {
148: $parts[] = $child;
149: }
150: $child = $child->next;
151: }
152: return $parts;
153: }
154:
155: 156: 157: 158:
159: public function getPath() {
160: $path = '';
161:
162: $child = $this->head;
163: while ($child) {
164: $type = $child->getType();
165: if ($type === T_NAMESPACE || $type === T_NS_SEPARATOR || $type === T_STRING) {
166: $path .= $child->getText();
167: }
168: $child = $child->next;
169: }
170: return $path;
171: }
172:
173: 174: 175: 176: 177: 178: 179: 180: 181:
182: protected function resolveUnqualified($name) {
183: if ($this->parent instanceof NamespaceNode) {
184: return '\\' . $name;
185: }
186: if ($this->parent instanceof UseDeclarationNode) {
187: return '\\' . $name;
188: }
189: $namespace = $this->getNamespace();
190: $use_declarations = array();
191: if ($namespace) {
192: $use_declarations = $namespace->getBody()->getUseDeclarations();
193: }
194: else {
195:
196: $root_node = $this->closest(Filter::isInstanceOf('\Pharborist\RootNode'));
197: if ($root_node) {
198: $use_declarations = $root_node->getUseDeclarations();
199: }
200: }
201: if ($this->parent instanceof FunctionCallNode) {
202:
203: foreach ($use_declarations as $use_declaration) {
204: if ($use_declaration->isFunction() && $use_declaration->getBoundedName() === $name) {
205: return '\\' . $use_declaration->getName()->getPath();
206: }
207: }
208: return $this->getParentPath() . $name;
209: }
210: elseif ($this->parent instanceof ConstantNode) {
211:
212: foreach ($use_declarations as $use_declaration) {
213: if ($use_declaration->isConst() && $use_declaration->getBoundedName() === $name) {
214: return '\\' . $use_declaration->getName()->getPath();
215: }
216: }
217: return $this->getParentPath() . $name;
218: }
219: else {
220:
221:
222: foreach ($use_declarations as $use_declaration) {
223: if ($use_declaration->isClass() && $use_declaration->getBoundedName() === $name) {
224: return '\\' . $use_declaration->getName()->getPath();
225: }
226: }
227:
228: return $this->getParentPath() . $name;
229: }
230: }
231:
232: 233: 234: 235:
236: public function getAbsolutePath() {
237:
238: $info = $this->getPathInfo();
239: $absolute = $info['absolute'];
240: $relative = $info['relative'];
241: $parts = $info['parts'];
242:
243: if (!$absolute && !$relative) {
244: $path = $this->resolveUnqualified($parts[0]->getText());
245: unset($parts[0]);
246: if (!empty($parts)) {
247: $path .= '\\';
248: }
249: }
250: else {
251: $path = $absolute ? '\\' : $this->getParentPath();
252: if ($parts[0]->getType() === T_NAMESPACE) {
253: unset($parts[0]);
254: }
255: }
256: $path .= implode('\\', $parts);
257: return $path;
258: }
259:
260: 261: 262: 263: 264: 265:
266: public function isGlobal() {
267: return $this->getParentPath() === '\\';
268: }
269:
270:
271: 272: 273: 274: 275: 276:
277: public function getBaseName() {
278: $path = $this->getAbsolutePath();
279: $parts = explode('\\', $path);
280: return end($parts);
281: }
282: }
283: