annotate class.template.php @ 11:a7ce1a423cbe

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