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