<?php

require_once('Transformer.php');
require_once(
'DOMUtils.php');

class 
RSS extends Transformer {

  private 
$domUtils;  
  private 
$itemFields;

  public function 
transform() {
    if (empty(
$this->extraArgs['link']))
      throw new 
MissingArgumentsException(array('link'));
    
    
// xmlDoc is responsible for the Dapp output
    
$xmlDoc = new DOMDocument();
    
$xmlDoc->loadXML($this->xmlContents);
    
$xmlRoot $xmlDoc->documentElement;    
    
    
$encoding 'UTF-8';
    
$dapperTag $xmlRoot->getElementsByTagName('dapper')->item(0);
    if (
$dapperTag) {
      
$encodingTag $dapperTag->getElementsByTagName('encoding')->item(0);
      if (
$encodingTag)
        
$encoding $encodingTag->nodeValue;
    }
    
    
$outputXml = new DOMDocument('1.0'$encoding);
    
$rssTag    $outputXml->createElement('rss');
    
$rssTag->setAttribute('version','2.0');
    
$outputXml->appendChild($rssTag);    

    
$this->domUtils = new DOMUtils($outputXml);
    
    
$channelTag $this->domUtils->createElement($rssTag'channel');
    
$this->domUtils->createElement($channelTag'link''http://www.dapper.net');
    
$this->domUtils->createElement($channelTag'title''Dapp RSS: '.$this->getDappName());
    
$this->domUtils->createElement($channelTag'description''Transformation of Dapp into RSS');
    
$this->domUtils->createElement($channelTag'webMaster''info@dapper.net');
    
$this->domUtils->createElement($channelTag'pubDate'date('r'));
    
    
    
// if there was an error, then we should process that and generate a 
    // "story" in the rss indicating that
    
$this->xpath = new DOMXPath($xmlDoc);
    
$messages $this->xpath->query("/results/message");
    if (
$messages->length 0) {
      
$errorItemTag $this->domUtils->createElement($channelTag'item');
      
$this->domUtils->createElement($errorItemTag'title''Error Making RSS Feed');
      
$this->domUtils->createElement($errorItemTag'description'$messages->item(0)->nodeValue);
      
$this->domUtils->createElement($errorItemTag'link''http://www.dapper.net/dapp-howto-use.php?'.$this->getDappName());

      
header('Content-type: text/xml; charset='.$encoding);
      echo 
$outputXml->saveXML();
      exit;
    }
    
    
//$groupsOrFields = $xmlRoot->childNodes;
    
$groupsOrFields $this->xpath->query('//*[@type="group" or @type="field"]');
    for (
$i=0$i<$groupsOrFields->length$i++) {
      
$childNode $groupsOrFields->item($i);

      if (
$childNode->nodeType != XML_ELEMENT_NODE)
        continue;

      if (
$childNode->getAttribute('type') == 'group') {
        
$this->itemFields = array();

        
$itemTag $this->domUtils->createElement($channelTag'item');
        
        
$fields $childNode->childNodes;
        
// this loop sets up $this->itemFields
        
for ($j=0$j<$fields->length$j++) {
          
$this->getFieldValue($fields->item($j));
        }
        foreach (
$this->itemFields as $rssField => $fieldValues) {
          
$this->domUtils->createElement($itemTag$rssFieldjoin(', ',$fieldValues));
        }
      }
      
// we make a fairly feeble attempt to handle ungrouped fields, at the top
      // level only (doesn't work for double dapps)
      
elseif ($childNode->getAttribute('type') == 'field') {
        
// we do not care about grouped fields, because they'll get taken care of by the groups
        
if ($childNode->parentNode->getAttribute('type') == 'group')
          continue;
        
        
$this->itemFields = array();
        
$this->getFieldValue($childNode);
        
        if (
sizeof($this->itemFields)) {
          
$itemTag $this->domUtils->createElement($channelTag'item');
          foreach (
$this->itemFields as $rssField => $fieldValues) {
            
$this->domUtils->createElement($itemTag$rssFieldjoin(', ',$fieldValues));
          }          
        }
                
      }
    }

    
    
header('Content-type: text/xml; charset='.$encoding);
    echo 
$outputXml->saveXML();
  }
  
  private function 
getFieldValue($fieldNode) {
    if (
$fieldNode->nodeType != XML_ELEMENT_NODE)
      return;

    if (
$fieldNode->getAttribute('type') == 'field') {
      
// list of acceptable rss fields      
      
$rssFields = array('title','link','description','pubDate','category');
      
      
// if the user specified that this field is to be included in rss
      // make sure it's a valid field and then include it
      
$fieldName $fieldNode->tagName;
      foreach (
$this->extraArgs as $rssFieldName => $dappFieldNames) {
        if (
in_array($rssFieldName,$rssFields)) {
          
          
$value $fieldNode->nodeValue;
          
          
// some times we define more than one dapp field for an rss field
          // but most often we do not
          
if (!is_array($dappFieldNames))
            
$dappFieldNames = array($dappFieldNames);
          
          
// if we have been asked to map an attribute to an rss field
          
foreach ($dappFieldNames as $dappFieldName) {
            if (
preg_match('/(.*)@(.*)/',$dappFieldName,$matches)) {
              
$dappFieldName $matches[1];
              
$value         $fieldNode->getAttribute($matches[2]);
            }
            
            if (
$dappFieldName == $fieldName) {
              
// if we have been asked to fix dates
              
if ($rssFieldName == 'pubDate' && !empty($this->extraArgs['fixDates'])) {
                
$dateValue strtotime($value);
                if (
$dateValue !== false)
                  
$value date('r'$dateValue);
              }
              
              
$this->itemFields[$rssFieldName][] = $value;
            }
          }
        }
      }
    }
  }

  public static function 
getDetails() {
    
$details = array();
    
    
$details['args']['title']       = array('type'     => DAPP_FIELD,
                                            
'required' => false,
                                            
'display'  => 'Item Title');
    
$details['args']['description'] = array('type'     => DAPP_FIELD_MULTI,
                                            
'required' => false,
                                            
'display'  => 'Item Description');
    
$details['args']['link']        = array('type'     => DAPP_FIELD_OR_ATTRIBUTE,
                                            
'required' => true,
                                            
'display'  => 'Item Link',
                                            
'valid'    => '^http://');
    
$details['args']['pubDate']     = array('type'     => DAPP_FIELD,
                                            
'required' => false,
                                            
'display'  => 'Item Date');
    
    
$details['args']['fixDates']    = array('type'     => USER_CHECKBOX,
                                            
'required' => false,
                                            
'value'    => 1,
                                            
'display'  => 'Fix Dates (experimental)');

    
$details['description']   = 'Transforms the output of a Dapp into RSS. If '.
                                
'the Dapp includes more than one field, the '.
                                
'fields should be grouped for this transformer '.
                                
'to work properly';
    
    return 
$details;
  }

}

?>