parts = self::prepareName($name); } public function getSubNodeNames() { return array('parts'); } /** * Gets the first part of the name, i.e. everything before the first namespace separator. * * @return string First part of the name */ public function getFirst() { return $this->parts[0]; } /** * Gets the last part of the name, i.e. everything after the last namespace separator. * * @return string Last part of the name */ public function getLast() { return $this->parts[count($this->parts) - 1]; } /** * Checks whether the name is unqualified. (E.g. Name) * * @return bool Whether the name is unqualified */ public function isUnqualified() { return 1 == count($this->parts); } /** * Checks whether the name is qualified. (E.g. Name\Name) * * @return bool Whether the name is qualified */ public function isQualified() { return 1 < count($this->parts); } /** * Checks whether the name is fully qualified. (E.g. \Name) * * @return bool Whether the name is fully qualified */ public function isFullyQualified() { return false; } /** * Checks whether the name is explicitly relative to the current namespace. (E.g. namespace\Name) * * @return bool Whether the name is relative */ public function isRelative() { return false; } /** * Returns a string representation of the name by imploding the namespace parts with the * namespace separator. * * @return string String representation */ public function toString() { return implode('\\', $this->parts); } /** * Returns a string representation of the name by imploding the namespace parts with the * namespace separator. * * @return string String representation */ public function __toString() { return implode('\\', $this->parts); } /** * Gets a slice of a name (similar to array_slice). * * This method returns a new instance of the same type as the original and with the same * attributes. * * If the slice is empty, null is returned. The null value will be correctly handled in * concatenations using concat(). * * Offset and length have the same meaning as in array_slice(). * * @param int $offset Offset to start the slice at (may be negative) * @param int|null $length Length of the slice (may be negative) * * @return static|null Sliced name */ public function slice($offset, $length = null) { $numParts = count($this->parts); $realOffset = $offset < 0 ? $offset + $numParts : $offset; if ($realOffset < 0 || $realOffset > $numParts) { throw new \OutOfBoundsException(sprintf('Offset %d is out of bounds', $offset)); } if (null === $length) { $realLength = $numParts - $realOffset; } else { $realLength = $length < 0 ? $length + $numParts - $realOffset : $length; if ($realLength < 0 || $realLength > $numParts) { throw new \OutOfBoundsException(sprintf('Length %d is out of bounds', $length)); } } if ($realLength === 0) { // Empty slice is represented as null return null; } return new static(array_slice($this->parts, $realOffset, $realLength), $this->attributes); } /** * Concatenate two names, yielding a new Name instance. * * The type of the generated instance depends on which class this method is called on, for * example Name\FullyQualified::concat() will yield a Name\FullyQualified instance. * * If one of the arguments is null, a new instance of the other name will be returned. If both * arguments are null, null will be returned. As such, writing * Name::concat($namespace, $shortName) * where $namespace is a Name node or null will work as expected. * * @param string|array|self|null $name1 The first name * @param string|array|self|null $name2 The second name * @param array $attributes Attributes to assign to concatenated name * * @return static|null Concatenated name */ public static function concat($name1, $name2, array $attributes = []) { if (null === $name1 && null === $name2) { return null; } elseif (null === $name1) { return new static(self::prepareName($name2), $attributes); } else if (null === $name2) { return new static(self::prepareName($name1), $attributes); } else { return new static( array_merge(self::prepareName($name1), self::prepareName($name2)), $attributes ); } } /** * Prepares a (string, array or Name node) name for use in name changing methods by converting * it to an array. * * @param string|array|self $name Name to prepare * * @return array Prepared name */ private static function prepareName($name) { if (\is_string($name)) { return explode('\\', $name); } elseif (\is_array($name)) { return $name; } elseif ($name instanceof self) { return $name->parts; } throw new \InvalidArgumentException( 'Expected string, array of parts or Name instance' ); } }