diff options
Diffstat (limited to 'ext/spl/internal/recursiveiteratoriterator.inc')
-rw-r--r-- | ext/spl/internal/recursiveiteratoriterator.inc | 237 |
1 files changed, 237 insertions, 0 deletions
diff --git a/ext/spl/internal/recursiveiteratoriterator.inc b/ext/spl/internal/recursiveiteratoriterator.inc new file mode 100644 index 0000000..35fa801 --- /dev/null +++ b/ext/spl/internal/recursiveiteratoriterator.inc @@ -0,0 +1,237 @@ +<?php + +/** @file recursiveiteratoriterator.inc + * @ingroup SPL + * @brief class RecursiveIteratorIterator + * @author Marcus Boerger + * @date 2003 - 2009 + * + * SPL - Standard PHP Library + */ + +/** + * @brief Iterates through recursive iterators + * @author Marcus Boerger + * @version 1.2 + * @since PHP 5.0 + * + * The objects of this class are created by instances of RecursiveIterator. + * Elements of those iterators may be traversable themselves. If so these + * sub elements are recursed into. + */ +class RecursiveIteratorIterator implements OuterIterator +{ + /** Mode: Only show leaves */ + const LEAVES_ONLY = 0; + /** Mode: Show parents prior to their children */ + const SELF_FIRST = 1; + /** Mode: Show all children prior to their parent */ + const CHILD_FIRST = 2; + + /** Flag: Catches exceptions during getChildren() calls and simply jumps + * to the next element. */ + const CATCH_GET_CHILD = 0x00000002; + + private $ait = array(); + private $count = 0; + private $mode = self::LEAVES_ONLY; + private $flags = 0; + + /** Construct from RecursiveIterator + * + * @param it RecursiveIterator to iterate + * @param mode Operation mode (one of): + * - LEAVES_ONLY only show leaves + * - SELF_FIRST show parents prior to their childs + * - CHILD_FIRST show all children prior to their parent + * @param flags Control flags, zero or any combination of the following + * (since PHP 5.1). + * - CATCH_GET_CHILD which catches exceptions during + * getChildren() calls and simply jumps to the next + * element. + */ + function __construct(RecursiveIterator $it, $mode = self::LEAVES_ONLY, $flags = 0) + { + $this->ait[0] = $it; + $this->mode = $mode; + $this->flags = $flags; + } + + /** Rewind to top iterator as set in constructor + */ + function rewind() + { + while ($this->count) { + unset($this->ait[$this->count--]); + $this->endChildren(); + } + $this->ait[0]->rewind(); + $this->ait[0]->recursed = false; + callNextElement(true); + } + + /** @return whether iterator is valid + */ + function valid() + { + $count = $this->count; + while ($count) { + $it = $this->ait[$count]; + if ($it->valid()) { + return true; + } + $count--; + $this->endChildren(); + } + return false; + } + + /** @return current key + */ + function key() + { + $it = $this->ait[$this->count]; + return $it->key(); + } + + /** @return current element + */ + function current() + { + $it = $this->ait[$this->count]; + return $it->current(); + } + + /** Forward to next element + */ + function next() + { + while ($this->count) { + $it = $this->ait[$this->count]; + if ($it->valid()) { + if (!$it->recursed && callHasChildren()) { + $it->recursed = true; + try + { + $sub = callGetChildren(); + } + catch (Exception $e) + { + if (!($this->flags & self::CATCH_GET_CHILD)) + { + throw $e; + } + $it->next(); + continue; + } + $sub->recursed = false; + $sub->rewind(); + if ($sub->valid()) { + $this->ait[++$this->count] = $sub; + if (!$sub instanceof RecursiveIterator) { + throw new Exception(get_class($sub).'::getChildren() must return an object that implements RecursiveIterator'); + } + $this->beginChildren(); + return; + } + unset($sub); + } + $it->next(); + $it->recursed = false; + if ($it->valid()) { + return; + } + $it->recursed = false; + } + if ($this->count) { + unset($this->ait[$this->count--]); + $it = $this->ait[$this->count]; + $this->endChildren(); + callNextElement(false); + } + } + callNextElement(true); + } + + /** @return Sub Iterator at given level or if unspecified the current sub + * Iterator + */ + function getSubIterator($level = NULL) + { + if (is_null($level)) { + $level = $this->count; + } + return @$this->ait[$level]; + } + + /** + * @return The inner iterator + */ + function getInnerIterator() + { + return $this->it; + } + + /** @return Current Depth (Number of parents) + */ + function getDepth() + { + return $this->level; + } + + /** @return whether current sub iterators current element has children + * @since PHP 5.1 + */ + function callHasChildren() + { + return $this->ait[$this->count]->hasChildren(); + } + + /** @return current sub iterators current children + * @since PHP 5.1 + */ + function callGetChildren() + { + return $this->ait[$this->count]->getChildren(); + } + + /** Called right after calling getChildren() and its rewind(). + * @since PHP 5.1 + */ + function beginChildren() + { + } + + /** Called after current child iterator is invalid and right before it + * gets destructed. + * @since PHP 5.1 + */ + function endChildren() + { + } + + private function callNextElement($after_move) + { + if ($this->valid()) + { + if ($after_move) + { + if (($this->mode == self::SELF_FIRST && $this->callHasChildren()) + || $this->mode == self::LEAVES_ONLY) + $this->nextElement(); + } + else + { + $this->nextElement(); + } + } + } + + /** Called when the next element is available + */ + function nextElement() + { + } +} + +?>
\ No newline at end of file |