view class.template.php @ 0:c86959030ae8

Import initial
author Franck Deroche <webmaster@defr.net>
date Sat, 10 Mar 2007 21:48:42 +0100
parents
children 0f40a8a39c68
line wrap: on
line source
<?php
class Template {
    var $xmlDocument;
    var $xmlXPath;
    
    const NS = 'http://defr.net/2007/template';
    
    function __construct($fileName) {
        $this->xmlDocument->validateOnParse = true;
        $this->xmlDocument = DOMDocument::loadXML(file_get_contents($fileName));
        $this->xmlXPath = new DOMXPath($this->xmlDocument);
    }
    
    function apply($selector, $obj) {
        $rootSelector = $this->parseSelector($selector);
        // Cloning test
        if(is_array($obj)) {
            foreach($obj as $array) {
                foreach($rootSelector->nodes as $node) {
                    $nodeName = key($array);
                    $tmp = $this->getClonedNode($node, $nodeName);
                    $futureNode = $tmp->clone;
                    $node->insertBefore($futureNode, $tmp->orig);
                    foreach($array as $sel => $test) {
                        $content = $this->parseReplacement($test);
                        $localSelector = $this->parseSelector($sel);
                        if(isset($localSelector->attribute))
                            $futureNode->setAttribute($localSelector->attribute, $test);
                        else {
                            if($futureNode->namespaceURI == Template::NS)
                                $this->replaceNode($futureNode, $content);
                            else
                                $this->setNodeContent($futureNode, $content);
                        }
                    }
                }
            }
        } else
        {
            $content = $this->parseReplacement($obj);
            foreach($rootSelector->nodes as $node) {
                if(isset($rootSelector->attribute)) {
                    $node->setAttribute($rootSelector->attribute, $obj);
                } else {
                    if($node->namespaceURI == Template::NS)
                        $this->replaceNode($node, $content);
                    else
                        $this->setNodeContent($node, $content);
                }
            }
        }
    }
    
    function getClonedNode($node, $childNodeName) {
        $canditates = $node->getElementsByTagName($childNodeName);
        foreach($canditates as $canditate) {
            if($canditate->nodeName == $childNodeName && $canditate->getAttributeNS(Template::NS, 'toClone') == 'true') {
                $tmp = array();
                $tmp['orig'] = $canditate;
                $cnode = $canditate->cloneNode(true);
                $cnode->removeAttribute('toClone');
                $tmp['clone'] = $cnode;
                return (object)$tmp;
            }
        }
    }
    
    function parseSelector($selector, DOMElement $root=NULL) {
        if(!($root instanceof DOMElement)) {
            $root = $this->xmlDocument->documentElement;
        }
        $obj = array();
        $pos = strpos($selector, '@');
        if($pos !== false) {
            $obj['attribute'] = substr($selector,$pos +1);
            $selector = substr($selector, 0, $pos);
        }
        if($selector[0] == '#') {
            $obj['xpath'] = "//*[@t:id='" . substr($selector, 1) . "']";
            $obj['nodes'] = $this->xmlXPath->query($obj['xpath'], $root);
        }
        else {
            $obj['nodeName'] = $selector;
            $obj['nodes'] = $root->getElementsByTagName($selector);
            $obj['nodes'] = $this->xmlDocument->getElementsByTagName($selector);
        }
        return (object)$obj;
    }
    
    function getNodesMatching($selector, DOMElement $root) {
        $pos = strpos($selector, '/');
        if($pos !== false) {
            $currentSelector = substr($selector, 0, $pos);
            $remainingSelector = substr($selector, $pos+1);
        }
        else {
            $currentSelector = $selector;
            $remainingSelector = NULL;
        }
        if($selector[0] == '#') {
            $nodes = $this->xmlXPath->query($currentSelector, $root);
        }
        else {
            
        }
    }
    
    function parseReplacement($obj) {
        $retVal = NULL;
        if(is_string($obj))
            $retVal = $this->xmlDocument->createTextNode($obj);
        else if($obj instanceof DOMDocument)
            $retVal = $obj->documentElement;
        else if($obj instanceof DOMNode)
            $retVal = $obj;
        return $retVal;
    }
    
    function setParams($array) {
        foreach($array as $selector => $obj) {
            $this->apply($selector, $obj);
        }
    }
    
    function replaceNode(DOMNode $node, DOMNode $content) {
        $parent = $node->parentNode;
        $parent->replaceChild($content, $node);
    }
    
    function setNodeContent(DOMElement $node, DOMNode $content) {
        // Suppress existing childs
        foreach($node->childNodes as $child) {
            $node->removeChild($child);
        }
        // Add the new child
        $node->appendChild($content);
    }
    
    function clean() {
        // Suppression des noeuds à cloner
        $nodes = $this->xmlXPath->query("//*[@t:toClone]|//t:*");
        foreach($nodes as $node) {
            if($node->parentNode) {
                $node->parentNode->removeChild($node);
            }
        }
    }
    
    function __toString() {
        $this->clean();
        $this->xmlDocument->saveXML();
        return $this->xmlDocument->saveXML();
    }
}