view class.template.php @ 2:ad12469f4db4

Initialisation de xmlDocument, puis chargement. Avant, on faisait un xmlDocument->validateOnParse sans avoir initialiser (donc, sur un NULL, c'est etrange que PHP n'est pas bronche), puis on utilisait une methode statique sur DOMDocument... Passage en privee des deux variables.
author Franck Deroche <webmaster@defr.net>
date Fri, 16 Mar 2007 16:01:10 +0100
parents 0f40a8a39c68
children a76a46cbb401
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) {
        $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) {
        $candidates = $node->getElementsByTagName($childNodeName);
        foreach($candidates as $candidate) {
            if($candidate->nodeName == $childNodeName && $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=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();
    }
}