<?php
/**
 * Implements the RecusrsiveIteratorIterator for Url map.
 *
 * @version 1.0
 * @package Library
 * @author Miroslav Kubelik (koubel@volny.cz)
 * @copyright Copyright (c) 2007-2009 Miroslav Kubelik
 * @license http://opensource.org/licenses/gpl-license.php GNU GPL
 */
/**
 * The recursive Iterator on Iterator (RecursiveItaratorIterator in SPL like syntax) for the URL's map.
 * It is based on nice SPL library. Insipired by SPL
 * {@link http://www.php.net/~helly/php/ext/spl/directorytreeiterator_8inc-source.html DirectoryTreeIterator}.
 *
 * This iterator iterates over SPL SimpleXMLIterator (which extends SimpleXMLElement),
 * which is build from the xml file, which describe the structure of URLs. One Url map is mostly used for
 * one controller (in the sense of the Zend framework MVC).
 *
 * Class can be used in every iteration (for,foreach,while...). It sets URL path and syntax path for current
 * element. Elements with URL must have "name" element as child. Content of this "name" element
 * is ID of URL.
 *
 * @package Library
 * @author Miroslav Kubelik (koubel@volny.cz)
 * @copyright Copyright (c) 2007-2009 Miroslav Kubelik
 * @license http://opensource.org/licenses/gpl-license.php GNU GPL
 */
class UrlMapIterator extends RecursiveIteratorIterator {
    /**
     * Whole url path for current "link" xml element.
     * This is built hierarchically.
     * @var string
     */
    private $urlPath;
    /**
     * Syntax path current SimpleXMLIterator is built from "name" elemnets
     * This is built hierarchically from root URL element.
     * @var string
     */
    private $syntaxPath;
    /**
     * current URL from name XML element
     * @var string
     */
    private $currentName;

    /**
     * Build iterator as RecursiveIteratorIterator from outer RecursiveCachingIterator
     * which wrapps SimpleXMLIterator.
     */
    public function __construct($xmlfile) {
        $sxe = simplexml_load_file($xmlfile, 'SimpleXMLIterator');
        parent::__construct(new RecursiveCachingIterator($sxe), parent::SELF_FIRST);
    }

    /**
     * Return current URL path, {@see urlPath}.
     * @return string
     */
    public function getCurrentUrlPath() {
        $this->current();
        return $this->urlPath;
    }

    /**
     * Return current URL identifier (name).
     * @return string
     */
    public function getCurrentName() {
        $this->current();
        return $this->currentName;
    }

    /**
     * Return current syntax path URL identifier (name).
     * @return string
     */
    public function getCurrentSyntaxPath() {
        $this->current();
        return $this->syntaxPath;
    }

    /**
     * Reset URL path, syntax path and current element name members to the empty string.
     */
    private function resetAll() {
        $this->urlPath = "";
        $this->syntaxPath = "";
        $this->currentName = "";
    }

    /**
     * Return current SimpleXMLIterator. Set path, syntax path and current element
     * also.
     *
     * @return object SimpleXMLIterator
     */
    public function current() {
        $this->resetAll();
        //current node
        $xmlNode = parent::current();
        //if the current node has the "name" subnode, it means that the current node is node
        //with URL
        if (isset($xmlNode->name)) {
            //set path from previous nodes
            $this->setFromPrevious();
            $this->addFromNode($xmlNode);
            $this->currentName = (string)$xmlNode->name;
        }
        //echo current node
        return $xmlNode;
    }

    /**
     * Go through the root element to the current element and built URL path and
     * syntax path.
     */
    private function setFromPrevious() {
        //iterate in previous node
        for ($i = 0;$i < $this->getDepth();$i++) {
            $xmlNode = $this->getSubIterator($i)->getInnerIterator();
            //if the current node has the "name" subnode, it means that the current node is node with URL
            if (isset($xmlNode->name)) {
                $this->addFromNode($xmlNode);
            }
        }
    }

    /**
     * Add info from the current element to the path properties
     * @param SimpleXMLIterator $xmlNode current XML node
     */
    private function addFromNode(SimpleXMLIterator $xmlNode) {
        $this->urlPath.= (string)$xmlNode['url'];
        $this->syntaxPath.= empty($this->syntaxPath) ? (string)$xmlNode->name : "/" . (string)$xmlNode->name;
    }

}
