<?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);
}
}
}
?>
|