<?php

// NOTE: this transformer is not double-dapp safe!

require_once('Transformer.php');

class 
JSON extends Transformer {
  
  private 
$xpath;

  public function 
transform() {
    
$xmlDoc  = new DOMDocument();
    
    if (!
$xmlDoc->loadXML($this->xmlContents)) {
      throw new 
Exception("Unable to DOMify XML (XML looks like: ".$this->xmlContents.')');
    }
    
$this->xpath   = new DOMXPath($xmlDoc);
        
    
header('Content-type: text/plain;charset='.
           
$this->xpath->query("/elements/dapper/encoding")->item(0)->nodeValue);

    
// start building the data structure we'll transform to JSON
    
$dataStructure = array();
    
    
// put all the dapper info into it
    
$dapperNodes $this->xpath->query("/elements/dapper/*");
    for (
$i 0$i $dapperNodes->length$i++) {
      
$dapperNode $dapperNodes->item($i);
      
$dataStructure['dapper'][$dapperNode->tagName] = $dapperNode->nodeValue;
    }

    
// take care of all the groups
    
$groupNodes $this->xpath->query('//*[@type="group"]');
    for (
$i 0$i $groupNodes->length$i++) {
      
$groupNode $groupNodes->item($i);
      
$groupArray = array();
      for (
$f 0$f $groupNode->childNodes->length$f++) {
        
$fieldNode $groupNode->childNodes->item($f);
        if (
$fieldNode->nodeType != XML_ELEMENT_NODE)
          continue;
          
        if (
$fieldNode->getAttribute('type') == 'field') {
          
$fieldArray $this->getFieldArray($fieldNode);
          if (
sizeof($fieldArray))
            
$groupArray[$fieldNode->tagName][] = $fieldArray;
        }
      }
      if (
sizeof($groupArray)) {
        
$dataStructure['groups'][$groupNode->tagName][] = $groupArray;
      }
    }

    
// take care of all the fields not in groups
    
$fieldNodes $this->xpath->query('//*[@type="field"]');
    for (
$i 0$i $fieldNodes->length$i++) {
      
$fieldNode $fieldNodes->item($i);
      if (
$fieldNode->parentNode->getAttribute('type') != 'group') {
        
$fieldArray $this->getFieldArray($fieldNode);
        
$dataStructure['fields'][$fieldNode->tagName][] = $fieldArray;
      }
    }

    echo 
$this->encode($dataStructure);
  }
  
  public function 
getFieldArray($fieldNode) {
    
$fieldArray = array();
    
$fieldArray['value'] = $fieldNode->nodeValue;
    if (
$fieldNode->getAttribute('href'))
      
$fieldArray['href'] = $fieldNode->getAttribute('href');
    if (
$fieldNode->getAttribute('src'))
      
$fieldArray['src'] = $fieldNode->getAttribute('src');
    
$fieldArray['originalElement'] = $fieldNode->getAttribute('originalElement');    
    return 
$fieldArray;
  }

  public static function 
getDetails() {
    
$details 
      array(
'description' => 'Transforms the output of a Dapp into JSON, '.
                             
'which can be used in a variety of programming '.
                             
'languages and eliminates the need for XML '.
                             
'parsing');
    
    
$details['args']['callbackFunctionWrapper'] = 
      array(
'type'     => USER_FREEFORM,
            
'required' => false,
            
'display'  => 'Callback function name (optional)');
    
    return 
$details;
  }
  
  protected function 
encode($structure) {
    
$encoded json_encode($structure);
    if (empty(
$this->extraArgs['callbackFunctionWrapper']))
      return 
$encoded;
      
    
// if a callback function is supplied, wrap it - by request of
    // dapper@greg-hill.id.au
    
else
      return 
$this->extraArgs['callbackFunctionWrapper'].'( '.$encoded.' );';
  }

}

?>