Overview

Namespaces

  • Pharborist
    • Constants
    • ControlStructures
    • Exceptions
    • Functions
    • Generators
    • Namespaces
    • Objects
    • Operators
    • Types
    • Variables

Classes

  • Pharborist\Variables\CompoundVariableNode
  • Pharborist\Variables\GlobalStatementNode
  • Pharborist\Variables\ReferenceVariableNode
  • Pharborist\Variables\StaticVariableNode
  • Pharborist\Variables\StaticVariableStatementNode
  • Pharborist\Variables\VariableNode
  • Pharborist\Variables\VariableVariableNode

Interfaces

  • Pharborist\Variables\VariableExpressionNode
  • Overview
  • Namespace
  • Class
  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:  * The name of namespace, function, constant, class, trait or interface.
 13:  *
 14:  * This node is used for things whose name is namespace-aware. Variables, for
 15:  * example, cannot be namespaced, but classes can. That's why class names
 16:  * are wrapped by NameNode: because NameNodes are aware of the namespace they
 17:  * live in, even when moved from one namespace to another.
 18:  */
 19: class NameNode extends ParentNode {
 20:   /**
 21:    * Create namespace path.
 22:    *
 23:    * @param string $name
 24:    * @return NameNode
 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:    * Get the namespace that owns this name.
 43:    *
 44:    * @return NamespaceNode
 45:    *   The namespace that owns this node.
 46:    */
 47:   public function getNamespace() {
 48:     return $this->closest(Filter::isInstanceOf('\Pharborist\Namespaces\NamespaceNode'));
 49:   }
 50: 
 51:   /**
 52:    * @return string
 53:    */
 54:   public function getParentPath() {
 55:     if ($this->parent instanceof NamespaceNode) {
 56:       return '\\';
 57:     }
 58:     if ($this->isAbsolute()) {
 59:       return '\\';
 60:     }
 61:     /** @var NamespaceNode $namespace */
 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:    * Return information about the name.
 77:    * @return array
 78:    */
 79:   public function getPathInfo() {
 80:     /** @var TokenNode $first */
 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:    * Return TRUE if the name is an absolute name.
 96:    * Eg. \TopNamespace\SubNamespace\MyClass
 97:    * @return bool
 98:    */
 99:   public function isAbsolute() {
100:     /** @var TokenNode $first */
101:     $first = $this->firstChild();
102:     return $first->getType() === T_NS_SEPARATOR;
103:   }
104: 
105:   /**
106:    * Return TRUE if the name is a relative name.
107:    * Eg. namespace\MyClass
108:    * @return bool
109:    */
110:   public function isRelative() {
111:     /** @var TokenNode $first */
112:     $first = $this->firstChild();
113:     return $first->getType() === T_NAMESPACE;
114:   }
115: 
116:   /**
117:    * Return TRUE if the name is a qualified name.
118:    * Eg. MyNamespace\MyClass
119:    * @return bool
120:    */
121:   public function isUnqualified() {
122:     $absolute = $this->isAbsolute();
123:     $parts = $this->getParts();
124:     return !$absolute && count($parts) === 1;
125:   }
126: 
127:   /**
128:    * Return TRUE if the name is a qualified name.
129:    * Eg. MyNamespace\MyClass
130:    * @return bool
131:    */
132:   public function isQualified() {
133:     $absolute = $this->isAbsolute();
134:     $parts = $this->getParts();
135:     return !$absolute && count($parts) > 1;
136:   }
137: 
138:   /**
139:    * @return TokenNode[]
140:    */
141:   public function getParts() {
142:     $parts = [];
143:     /** @var TokenNode $child */
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:    * Get the namespace path.
157:    * @return string
158:    */
159:   public function getPath() {
160:     $path = '';
161:     /** @var TokenNode $child */
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:    * Resolve an unqualified name to fully qualified name.
175:    *
176:    * @param string $name
177:    *   The unqualified name to resolve.
178:    *
179:    * @return string
180:    *   Fully qualified name.
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:       /** @var \Pharborist\RootNode $root_node */
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:       /** @var UseDeclarationNode $use_declaration */
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:       /** @var UseDeclarationNode $use_declaration */
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:       // Name is a class reference.
221:       /** @var UseDeclarationNode $use_declaration */
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:       // No use declaration so class name refers to class in current namespace.
228:       return $this->getParentPath() . $name;
229:     }
230:   }
231: 
232:   /**
233:    * @return string
234:    *   The absolute namespace path.
235:    */
236:   public function getAbsolutePath() {
237:     /** @var TokenNode[] $parts */
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:    * Returns if this name is in the global namespace, which is functionally
262:    * the same as having no namespace.
263:    *
264:    * @return boolean
265:    */
266:   public function isGlobal() {
267:     return $this->getParentPath() === '\\';
268:   }
269: 
270: 
271:   /**
272:    * Returns trailing name component of path.
273:    *
274:    * @return string
275:    *   Last component of path.
276:    */
277:   public function getBaseName() {
278:     $path = $this->getAbsolutePath();
279:     $parts = explode('\\', $path);
280:     return end($parts);
281:   }
282: }
283: 
Pharborist API documentation generated by ApiGen