annotate class.template.php @ 17:d4ac7cef0cdd

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