elements; else throw new InvalidArgumentException(); } private static function compute ( $elements, $target ) { foreach ( $target as $elem ) if ( $elem === '.' ); elseif ( $elem === '..' ) { if ( count($elements) && end($elements) && end($elements) !== '..' ) array_pop($elements); elseif (!count($elements) || end($elements) === '..' ) $elements[] = $elem; } elseif ( $elem || !$elements ) $elements[] = $elem; return $elements; } private $elements; public function __construct ( $path ) { $this->elements = self::compute(array(), self::conv($path)); } public function getIterator () { return new ArrayIterator($this->elements); } public function isAbsolute () { return count($this->elements) && !$this->elements; } public function append ( $path ) { $source = $this->elements; foreach ( func_get_args() as $path ) $source = self::compute($source, self::conv($path)); return new self($source); } public function pop ( $path ) { $source = $this->elements; $target = self::compute(array(), self::conv($path)); foreach ( func_get_args() as $path ) { while ( count($source) && count($target) && last($source) === last($target) ) { array_pop($source); array_pop($target); } if ( count($target) ) return false; } return new self($source); } public function prepend ( $path ) { $source = $this->elements; foreach ( func_get_args() as $path ) $source = self::compute(self::conv($path), $source); return new self($source); } public function shift ( $path ) { $source = $this->elements; $target = self::compute(array(), self::conv($path)); foreach ( func_get_args() as $path ) { while ( count($source) && count($target) && reset($source) === reset($target) ) { array_shift($source); array_shift($target); } if ( count($target) ) return false; } return new self($source); } public function absolute () { return array_key_exists(0, $this->elements) && !$this->elements[0]; } public function __toString () { $abs = count($this->elements) === 1 && array_key_exists(0, $this->elements) && !$this->elements[0] ? DIRECTORY_SEPARATOR : ''; return $abs . implode(DIRECTORY_SEPARATOR, $this->elements); } } ?>