view class.template.php @ 7:61dee7e34a9d

Changer de nom de variable, c'est bien, mais faut l'faire partout.
author Franck Deroche <webmaster@defr.org>
date Sun, 21 Oct 2007 14:14:23 +0200
parents f80e9010e64d
children 0b796d56c767
line wrap: on
line source
<?php
class Template {
    private $xmlDocument;
    private $xmlXPath;
    
    const NS = 'http://defr.net/2007/template';
    
    function __construct($fileName, $shouldValidate = false) {
        $this->xmlDocument = new DOMDocument();
        $this->xmlDocument->validateOnParse = $shouldValidate;
        $this->xmlDocument->loadXML(file_get_contents($fileName));
        $this->xmlXPath = new DOMXPath($this->xmlDocument);
    }
    
    function apply($selector, $obj, DOMElement $root = null) {
        if(!($root instanceof DOMElement))
            $root = $this->xmlDocument->documentElement;
        $rootSelector = $this->parseSelector($selector, $root);
        if(is_array($obj))
            $this->applyClone($rootSelector, $obj, $root);
        else {
            foreach($rootSelector->nodes as $node) {
                $content = $this->parseReplacement($obj); 
                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 applyClone($rootSelector, $obj, $root) {
        foreach($obj as $array) {
            $nodeName = key($array);
	        foreach($rootSelector->nodes as $node) {
                $tmp = $this->getClonedNode($node, $nodeName);
                $futureNode = $tmp->clone;
                $futureNode = $node->insertBefore($futureNode, $tmp->orig);
                foreach($array as $sel => $test) {
                    $locSelector = $this->parseSelector($sel, $node);
                    if(isset($locSelector->attribute))
                        $futureNode->setAttribute($locSelector->attribute, $test);
                    else {
                        $content = $this->parseReplacement($test);
                        $node->insertBefore($content, $tmp->orig);
                        if($futureNode->namespaceURI == Template::NS)
                            $this->replaceNode($futureNode, $content);
                        else
                            $this->setNodeContent($futureNode, $content);
                    }
                }
	        }
        }
    }
    
    function getClonedNode($node, $childNodeName) {
        $candidates = $this->parseSelector($childNodeName, $node)->nodes;
        foreach($candidates as $candidate) {
            if($candidate->getAttributeNS(Template::NS, 'toClone') == 'true') {
                $tmp = array();
                $tmp['orig'] = $candidate;
                $cnode = $candidate->cloneNode(true);
                $cnode->removeAttributeNS(Template::NS, 'toClone');
                $tmp['clone'] = $cnode;
                return (object)$tmp;
            }
        }
    }
    
    function parseSelector($selector, DOMElement $root) {
        $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);
        }
        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->clone(true);
        else if($obj instanceof DOMNode)
            $retVal = $obj->clone(true);
        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();
    }
}