annotate 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
rev   line source
webmaster@0 1 <?php
webmaster@0 2 class Template {
webmaster@2 3 private $xmlDocument;
webmaster@2 4 private $xmlXPath;
webmaster@0 5
webmaster@0 6 const NS = 'http://defr.net/2007/template';
webmaster@0 7
webmaster@6 8 function __construct($fileName, $shouldValidate = false) {
webmaster@2 9 $this->xmlDocument = new DOMDocument();
webmaster@6 10 $this->xmlDocument->validateOnParse = $shouldValidate;
webmaster@9 11 $this->xmlDocument->preserveWhiteSpace = false;
webmaster@2 12 $this->xmlDocument->loadXML(file_get_contents($fileName));
webmaster@15 13 $this->xmlDocument->preserveWhiteSpace = false;
webmaster@0 14 $this->xmlXPath = new DOMXPath($this->xmlDocument);
webmaster@8 15 $this->xmlXPath->registerNamespace('_t', Template::NS);
webmaster@0 16 }
webmaster@0 17
webmaster@3 18 function apply($selector, $obj, DOMElement $root = null) {
webmaster@6 19 if(!($root instanceof DOMElement))
webmaster@3 20 $root = $this->xmlDocument->documentElement;
webmaster@3 21 $rootSelector = $this->parseSelector($selector, $root);
webmaster@6 22 if(is_array($obj))
webmaster@6 23 $this->applyClone($rootSelector, $obj, $root);
webmaster@3 24 else {
webmaster@0 25 foreach($rootSelector->nodes as $node) {
webmaster@3 26 $content = $this->parseReplacement($obj);
webmaster@15 27 if(isset($rootSelector->attribute))
webmaster@0 28 $node->setAttribute($rootSelector->attribute, $obj);
webmaster@15 29 else
webmaster@15 30 $this->setNodeContent($node, $content);
webmaster@0 31 }
webmaster@0 32 }
webmaster@0 33 }
webmaster@6 34
webmaster@6 35 function applyClone($rootSelector, $obj, $root) {
webmaster@6 36 foreach($obj as $array) {
webmaster@6 37 $nodeName = key($array);
webmaster@6 38 foreach($rootSelector->nodes as $node) {
webmaster@6 39 $tmp = $this->getClonedNode($node, $nodeName);
webmaster@6 40 $futureNode = $tmp->clone;
webmaster@6 41 $futureNode = $node->insertBefore($futureNode, $tmp->orig);
webmaster@6 42 foreach($array as $sel => $test) {
webmaster@6 43 $locSelector = $this->parseSelector($sel, $node);
webmaster@7 44 if(isset($locSelector->attribute))
webmaster@6 45 $futureNode->setAttribute($locSelector->attribute, $test);
webmaster@6 46 else {
webmaster@6 47 $content = $this->parseReplacement($test);
webmaster@6 48 $node->insertBefore($content, $tmp->orig);
webmaster@15 49 $this->setNodeContent($futureNode, $content);
webmaster@6 50 }
webmaster@6 51 }
webmaster@6 52 }
webmaster@6 53 }
webmaster@6 54 }
webmaster@0 55
webmaster@0 56 function getClonedNode($node, $childNodeName) {
webmaster@3 57 $candidates = $this->parseSelector($childNodeName, $node)->nodes;
webmaster@1 58 foreach($candidates as $candidate) {
webmaster@3 59 if($candidate->getAttributeNS(Template::NS, 'toClone') == 'true') {
webmaster@0 60 $tmp = array();
webmaster@1 61 $tmp['orig'] = $candidate;
webmaster@1 62 $cnode = $candidate->cloneNode(true);
webmaster@6 63 $cnode->removeAttributeNS(Template::NS, 'toClone');
webmaster@0 64 $tmp['clone'] = $cnode;
webmaster@0 65 return (object)$tmp;
webmaster@0 66 }
webmaster@0 67 }
webmaster@0 68 }
webmaster@0 69
webmaster@3 70 function parseSelector($selector, DOMElement $root) {
webmaster@0 71 $obj = array();
webmaster@0 72 $pos = strpos($selector, '@');
webmaster@0 73 if($pos !== false) {
webmaster@0 74 $obj['attribute'] = substr($selector,$pos +1);
webmaster@0 75 $selector = substr($selector, 0, $pos);
webmaster@0 76 }
webmaster@0 77 if($selector[0] == '#') {
webmaster@8 78 $obj['xpath'] = "//*[@_t:id='" . substr($selector, 1) . "']";
webmaster@0 79 $obj['nodes'] = $this->xmlXPath->query($obj['xpath'], $root);
webmaster@0 80 }
webmaster@0 81 else {
webmaster@0 82 $obj['nodeName'] = $selector;
webmaster@0 83 $obj['nodes'] = $root->getElementsByTagName($selector);
webmaster@0 84 }
webmaster@0 85 return (object)$obj;
webmaster@0 86 }
webmaster@0 87
webmaster@0 88 function parseReplacement($obj) {
webmaster@0 89 $retVal = NULL;
webmaster@0 90 if(is_string($obj))
webmaster@0 91 $retVal = $this->xmlDocument->createTextNode($obj);
webmaster@0 92 else if($obj instanceof DOMDocument)
webmaster@3 93 $retVal = $obj->documentElement->clone(true);
webmaster@0 94 else if($obj instanceof DOMNode)
webmaster@3 95 $retVal = $obj->clone(true);
webmaster@11 96 else if($obj instanceof Template) {
webmaster@11 97 $node = $obj->xmlDocument->documentElement;
webmaster@11 98 $retVal = $this->xmlDocument->importNode($node, true);
webmaster@11 99 }
webmaster@0 100 return $retVal;
webmaster@0 101 }
webmaster@0 102
webmaster@0 103 function setParams($array) {
webmaster@0 104 foreach($array as $selector => $obj) {
webmaster@0 105 $this->apply($selector, $obj);
webmaster@0 106 }
webmaster@0 107 }
webmaster@0 108
webmaster@0 109 function replaceNode(DOMNode $node, DOMNode $content) {
webmaster@0 110 $parent = $node->parentNode;
webmaster@0 111 $parent->replaceChild($content, $node);
webmaster@0 112 }
webmaster@0 113
webmaster@0 114 function setNodeContent(DOMElement $node, DOMNode $content) {
webmaster@0 115 // Suppress existing childs
webmaster@0 116 foreach($node->childNodes as $child) {
webmaster@0 117 $node->removeChild($child);
webmaster@0 118 }
webmaster@0 119 // Add the new child
webmaster@0 120 $node->appendChild($content);
webmaster@0 121 }
webmaster@0 122
webmaster@0 123 function clean() {
webmaster@0 124 // Suppression des noeuds à cloner
webmaster@8 125 $nodes = $this->xmlXPath->query("//*[@_t:toClone]|//_t:*");
webmaster@0 126 foreach($nodes as $node) {
webmaster@0 127 if($node->parentNode) {
webmaster@15 128 $parent = $node->parentNode;
webmaster@15 129 if(!$node->hasAttributeNS(Template::NS, 'toClone')) {
webmaster@15 130 while($node->hasChildNodes())
webmaster@15 131 $parent->insertBefore($node->firstChild, $node);
webmaster@15 132 }
webmaster@15 133 $parent->removeChild($node);
webmaster@0 134 }
webmaster@0 135 }
webmaster@0 136 }
webmaster@0 137
webmaster@0 138 function __toString() {
webmaster@0 139 $this->clean();
webmaster@9 140 $this->xmlDocument->formatOutput = true;
webmaster@15 141 $this->xmlDocument->normalizeDocument();
webmaster@0 142 return $this->xmlDocument->saveXML();
webmaster@0 143 }
webmaster@6 144 }