Mercurial > defr > templates
view class.template.php @ 15:51645aad97a8
Simplification du code, impliquant un changement important de comportement.
Avant, les balises dans l'espace de nom template n'apparaissant pas
dans les paramètres d'applications étaient supprimés. Maintenant,
leur contenu passe dans le template de base.
author | Franck Deroche <webmaster@defr.org> |
---|---|
date | Mon, 22 Oct 2007 16:04:12 +0200 |
parents | a7ce1a423cbe |
children | 7a3ce31086b3 |
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->preserveWhiteSpace = false; $this->xmlDocument->loadXML(file_get_contents($fileName)); $this->xmlDocument->preserveWhiteSpace = false; $this->xmlXPath = new DOMXPath($this->xmlDocument); $this->xmlXPath->registerNamespace('_t', Template::NS); } 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 $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); $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 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); else if($obj instanceof Template) { $node = $obj->xmlDocument->documentElement; $retVal = $this->xmlDocument->importNode($node, 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) { $parent = $node->parentNode; if(!$node->hasAttributeNS(Template::NS, 'toClone')) { while($node->hasChildNodes()) $parent->insertBefore($node->firstChild, $node); } $parent->removeChild($node); } } } function __toString() { $this->clean(); $this->xmlDocument->formatOutput = true; $this->xmlDocument->normalizeDocument(); return $this->xmlDocument->saveXML(); } }