<?php
 
/* --------------------------------------------------------------------------
 
 * XIRE - eXtendable Information Rendering Engine
 
 * --------------------------------------------------------------------------
 
 * LICENSE
 
 * Copyright (C) 2006  David Duong
 
 *
 
 * This library is free software; you can redistribute it and/or
 
 * modify it under the terms of the GNU Lesser General Public
 
 * License as published by the Free Software Foundation; either
 
 * version 2.1 of the License, or (at your option) any later version.
 
 *
 
 * This library is distributed in the hope that it will be useful,
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
 * Lesser General Public License for more details.
 
 *
 
 * You should have received a copy of the GNU Lesser General Public
 
 * License along with this library; if not, write to the Free Software
 
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
 * -------------------------------------------------------------------------- */
 
/**
 
 * Provides looping functionality
 
 */
 
class XIRE_Plugin_For extends XIRE_Plugin {
 
    private $templateNode;      // Template of inner block
 
    private $iteration;         // Current iteration
 
 
    // Only allow DOMElement
 
    // @todo support DOMAttr
 
    public function __construct (DOMElement $node, XIRE_Process $sender) {
 
        parent::__construct($node, $sender);
 
    }
 
 
    public function execute () {
 
        // keep track of the iteration
 
        $this->iteration = 0;
 
        if ($this->node->childNodes->length > 0) {
 
            // Create the template nodes
 
            $this->templateNode = $this->template->document->createDocumentFragment();
 
            while ($this->node->haschildNodes()) {
 
                $this->templateNode->appendChild($this->node->childNodes->item(0));
 
            }
 
            // determine the type of loop
 
            if ($this->node->hasAttribute('each')) {
 
                $this->each();
 
            } elseif ($this->node->hasAttribute('from') || $this->node->hasAttribute('to')) {
 
                $this->from();
 
            } elseif ($this->node->hasAttribute('while')) {
 
                $this->loop();  // 'while' can not be a function name
 
            }
 
            // clean up
 
            $this->node->parentNode->removeChild($this->node);
 
        }
 
    }
 
 
    /**
 
     * foreach type loop
 
     */
 
    private function each () {
 
        $each = $this->node->getAttribute('each');
 
        $array = $this->template->get($each, true);
 
        foreach ($array as $key => $value) {
 
            $this->setVariable('key', $key);
 
            $this->setVariable('value', $value);
 
            $this->iterate();
 
        }
 
    }
 
 
    /**
 
     * for i to n type loop
 
     */
 
    private function from () {
 
        $from = (int)$this->getAttribute('from', '0', false);
 
        $to = (int)$this->getAttribute('to', '0', false);
 
        if ($from > $to) {
 
            for ($i = $from; $i < $to; $x++) {
 
                $this->setVariable('i', $i);
 
                $this->iterate();
 
            }
 
        } elseif ($from < $to) {
 
            for ($i = $from; $i > $to; $x--) {
 
                $this->setVariable('i', $i);
 
                $this->iterate();
 
            }
 
        }
 
        // If from = to then do nothing
 
    }
 
 
    /**
 
     * while type loop
 
     */
 
    private function loop () {
 
        $while = $this->getAttribute('while', true, false);
 
        while ($this->getVariable($while, true)) {
 
            $this->iterate();
 
        }
 
    }
 
 
    /**
 
     * Clone the template node and process it
 
     */
 
    private function iterate () {
 
        // Keep track of iteration
 
        $this->setVariable('iteration', $this->iteration++);
 
        // Clone the template loop
 
        $fragment = $this->templateNode->cloneNode(true);
 
        // Proccess the cloned nodes
 
        $process = $this->template->createProcess();
 
        $children = array();
 
        foreach ($fragment->childNodes as $node) {
 
            $children[] = $node;
 
            $process->enqueue($node);
 
        }
 
        // Put the nodes back into for before processing to preserve scope
 
        $this->node->appendChild($fragment);
 
        // Process the nodes
 
        $process->process();
 
        // Get it back out the for element
 
        foreach ($children as $node) {
 
            $this->node->parentNode->insertBefore($node, $this->node);
 
        }
 
    }
 
}
 
 
?>
 
 |