annotate class.template.php @ 8:0b796d56c767

Suppression du pre-supposé selon lequel l'espace de template est prefixé t.
author Franck Deroche <webmaster@defr.org>
date Sun, 21 Oct 2007 14:18:09 +0200
parents 61dee7e34a9d
children d06e9d5ff344
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@2 11 $this->xmlDocument->loadXML(file_get_contents($fileName));
webmaster@0 12 $this->xmlXPath = new DOMXPath($this->xmlDocument);
webmaster@8 13 $this->xmlXPath->registerNamespace('_t', Template::NS);
webmaster@0 14 }
webmaster@0 15
webmaster@3 16 function apply($selector, $obj, DOMElement $root = null) {
webmaster@6 17 if(!($root instanceof DOMElement))
webmaster@3 18 $root = $this->xmlDocument->documentElement;
webmaster@3 19 $rootSelector = $this->parseSelector($selector, $root);
webmaster@6 20 if(is_array($obj))
webmaster@6 21 $this->applyClone($rootSelector, $obj, $root);
webmaster@3 22 else {
webmaster@0 23 foreach($rootSelector->nodes as $node) {
webmaster@3 24 $content = $this->parseReplacement($obj);
webmaster@0 25 if(isset($rootSelector->attribute)) {
webmaster@0 26 $node->setAttribute($rootSelector->attribute, $obj);
webmaster@0 27 } else {
webmaster@0 28 if($node->namespaceURI == Template::NS)
webmaster@0 29 $this->replaceNode($node, $content);
webmaster@0 30 else
webmaster@0 31 $this->setNodeContent($node, $content);
webmaster@0 32 }
webmaster@0 33 }
webmaster@0 34 }
webmaster@0 35 }
webmaster@6 36
webmaster@6 37 function applyClone($rootSelector, $obj, $root) {
webmaster@6 38 foreach($obj as $array) {
webmaster@6 39 $nodeName = key($array);
webmaster@6 40 foreach($rootSelector->nodes as $node) {
webmaster@6 41 $tmp = $this->getClonedNode($node, $nodeName);
webmaster@6 42 $futureNode = $tmp->clone;
webmaster@6 43 $futureNode = $node->insertBefore($futureNode, $tmp->orig);
webmaster@6 44 foreach($array as $sel => $test) {
webmaster@6 45 $locSelector = $this->parseSelector($sel, $node);
webmaster@7 46 if(isset($locSelector->attribute))
webmaster@6 47 $futureNode->setAttribute($locSelector->attribute, $test);
webmaster@6 48 else {
webmaster@6 49 $content = $this->parseReplacement($test);
webmaster@6 50 $node->insertBefore($content, $tmp->orig);
webmaster@6 51 if($futureNode->namespaceURI == Template::NS)
webmaster@6 52 $this->replaceNode($futureNode, $content);
webmaster@6 53 else
webmaster@6 54 $this->setNodeContent($futureNode, $content);
webmaster@6 55 }
webmaster@6 56 }
webmaster@6 57 }
webmaster@6 58 }
webmaster@6 59 }
webmaster@0 60
webmaster@0 61 function getClonedNode($node, $childNodeName) {
webmaster@3 62 $candidates = $this->parseSelector($childNodeName, $node)->nodes;
webmaster@1 63 foreach($candidates as $candidate) {
webmaster@3 64 if($candidate->getAttributeNS(Template::NS, 'toClone') == 'true') {
webmaster@0 65 $tmp = array();
webmaster@1 66 $tmp['orig'] = $candidate;
webmaster@1 67 $cnode = $candidate->cloneNode(true);
webmaster@6 68 $cnode->removeAttributeNS(Template::NS, 'toClone');
webmaster@0 69 $tmp['clone'] = $cnode;
webmaster@0 70 return (object)$tmp;
webmaster@0 71 }
webmaster@0 72 }
webmaster@0 73 }
webmaster@0 74
webmaster@3 75 function parseSelector($selector, DOMElement $root) {
webmaster@0 76 $obj = array();
webmaster@0 77 $pos = strpos($selector, '@');
webmaster@0 78 if($pos !== false) {
webmaster@0 79 $obj['attribute'] = substr($selector,$pos +1);
webmaster@0 80 $selector = substr($selector, 0, $pos);
webmaster@0 81 }
webmaster@0 82 if($selector[0] == '#') {
webmaster@8 83 $obj['xpath'] = "//*[@_t:id='" . substr($selector, 1) . "']";
webmaster@0 84 $obj['nodes'] = $this->xmlXPath->query($obj['xpath'], $root);
webmaster@0 85 }
webmaster@0 86 else {
webmaster@0 87 $obj['nodeName'] = $selector;
webmaster@0 88 $obj['nodes'] = $root->getElementsByTagName($selector);
webmaster@0 89 }
webmaster@0 90 return (object)$obj;
webmaster@0 91 }
webmaster@0 92
webmaster@0 93 function getNodesMatching($selector, DOMElement $root) {
webmaster@0 94 $pos = strpos($selector, '/');
webmaster@0 95 if($pos !== false) {
webmaster@0 96 $currentSelector = substr($selector, 0, $pos);
webmaster@0 97 $remainingSelector = substr($selector, $pos+1);
webmaster@0 98 }
webmaster@0 99 else {
webmaster@0 100 $currentSelector = $selector;
webmaster@0 101 $remainingSelector = NULL;
webmaster@0 102 }
webmaster@0 103 if($selector[0] == '#') {
webmaster@0 104 $nodes = $this->xmlXPath->query($currentSelector, $root);
webmaster@0 105 }
webmaster@0 106 else {
webmaster@0 107
webmaster@0 108 }
webmaster@0 109 }
webmaster@0 110
webmaster@0 111 function parseReplacement($obj) {
webmaster@0 112 $retVal = NULL;
webmaster@0 113 if(is_string($obj))
webmaster@0 114 $retVal = $this->xmlDocument->createTextNode($obj);
webmaster@0 115 else if($obj instanceof DOMDocument)
webmaster@3 116 $retVal = $obj->documentElement->clone(true);
webmaster@0 117 else if($obj instanceof DOMNode)
webmaster@3 118 $retVal = $obj->clone(true);
webmaster@0 119 return $retVal;
webmaster@0 120 }
webmaster@0 121
webmaster@0 122 function setParams($array) {
webmaster@0 123 foreach($array as $selector => $obj) {
webmaster@0 124 $this->apply($selector, $obj);
webmaster@0 125 }
webmaster@0 126 }
webmaster@0 127
webmaster@0 128 function replaceNode(DOMNode $node, DOMNode $content) {
webmaster@0 129 $parent = $node->parentNode;
webmaster@0 130 $parent->replaceChild($content, $node);
webmaster@0 131 }
webmaster@0 132
webmaster@0 133 function setNodeContent(DOMElement $node, DOMNode $content) {
webmaster@0 134 // Suppress existing childs
webmaster@0 135 foreach($node->childNodes as $child) {
webmaster@0 136 $node->removeChild($child);
webmaster@0 137 }
webmaster@0 138 // Add the new child
webmaster@0 139 $node->appendChild($content);
webmaster@0 140 }
webmaster@0 141
webmaster@0 142 function clean() {
webmaster@0 143 // Suppression des noeuds à cloner
webmaster@8 144 $nodes = $this->xmlXPath->query("//*[@_t:toClone]|//_t:*");
webmaster@0 145 foreach($nodes as $node) {
webmaster@0 146 if($node->parentNode) {
webmaster@0 147 $node->parentNode->removeChild($node);
webmaster@0 148 }
webmaster@0 149 }
webmaster@0 150 }
webmaster@0 151
webmaster@0 152 function __toString() {
webmaster@0 153 $this->clean();
webmaster@0 154 $this->xmlDocument->saveXML();
webmaster@0 155 return $this->xmlDocument->saveXML();
webmaster@0 156 }
webmaster@6 157 }