view class.template.php @ 3:a76a46cbb401

Fix lie a quelques problemes de selections. + Utilisation de parseSelector dans le mode de clonage. + parseReplacement clone maintenant ce qu'on lui passe pour pouvoir l'utiliser plusieurs fois + parseSelector n'affecte plus deux fois $obj['nodes']
author Franck Deroche <webmaster@defr.net>
date Fri, 16 Mar 2007 16:12:46 +0100
parents ad12469f4db4
children f80e9010e64d
line wrap: on
line source
<?php
class Template {
    private $xmlDocument;
    private $xmlXPath;
    
    const NS = 'http://defr.net/2007/template';
    
    function __construct($fileName) {
        $this->xmlDocument = new DOMDocument();
        $this->xmlDocument->validateOnParse = true;
        $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);
        // 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, $node);
                        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 {
            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 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->removeAttribute('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();
    }
}