add disclogs rss and sitemap and viewer
add disclogs rss and sitemap and viewer


Former-commit-id: cf7e993d742cf3770bb93293c41bb9e298a36776

[submodule "couchdb/couchdb-lucene"] [submodule "couchdb/couchdb-lucene"]
path = couchdb/couchdb-lucene path = couchdb/couchdb-lucene
url = https://github.com/rnewson/couchdb-lucene.git url = https://github.com/rnewson/couchdb-lucene.git
[submodule "couchdb/settee"] [submodule "couchdb/settee"]
path = couchdb/settee path = couchdb/settee
url = https://github.com/inadarei/settee.git url = https://github.com/inadarei/settee.git
[submodule "lib/php-diff"] [submodule "lib/php-diff"]
path = lib/php-diff path = lib/php-diff
url = https://github.com/chrisboulton/php-diff.git url = https://github.com/chrisboulton/php-diff.git
[submodule "lib/Requests"] [submodule "lib/Requests"]
path = lib/Requests path = lib/Requests
url = https://github.com/rmccue/Requests.git url = https://github.com/rmccue/Requests.git
[submodule "js/flotr2"] [submodule "js/flotr2"]
path = js/flotr2 path = js/flotr2
url = https://github.com/HumbleSoftware/Flotr2.git url = https://github.com/HumbleSoftware/Flotr2.git
[submodule "lib/phpquery"] [submodule "lib/phpquery"]
path = lib/phpquery path = lib/phpquery
url = https://github.com/TobiaszCudnik/phpquery.git url = https://github.com/TobiaszCudnik/phpquery.git
[submodule "js/sigma"] [submodule "js/sigma"]
path = js/sigma path = js/sigma
url = https://github.com/jacomyal/sigma.js.git url = https://github.com/jacomyal/sigma.js.git
[submodule "js/bubbletree"] [submodule "js/bubbletree"]
path = js/bubbletree path = js/bubbletree
url = https://github.com/okfn/bubbletree.git url = https://github.com/okfn/bubbletree.git
[submodule "lib/querypath"] [submodule "lib/querypath"]
path = lib/querypath path = lib/querypath
url = https://github.com/technosophos/querypath.git url = https://github.com/technosophos/querypath.git
[submodule "lib/amon-php"] [submodule "lib/amon-php"]
path = lib/amon-php path = lib/amon-php
url = https://github.com/martinrusev/amon-php.git url = https://github.com/martinrusev/amon-php.git
[submodule "documents/lib/parsedatetime"] [submodule "documents/lib/parsedatetime"]
path = documents/lib/parsedatetime path = documents/lib/parsedatetime
url = git://github.com/bear/parsedatetime.git url = git://github.com/bear/parsedatetime.git
  [submodule "lib/FeedWriter"]
  path = lib/FeedWriter
  url = https://github.com/mibe/FeedWriter
   
 
  *.pyc
<?php <?php
include('template.inc.php'); include('template.inc.php');
include_header_documents(""); include_header_documents("");
include_once('../include/common.inc.php'); include_once('../include/common.inc.php');
?> ?>
<?php <?php
   
   
   
$agenciesdb = $server->get_db('disclosr-agencies'); $agenciesdb = $server->get_db('disclosr-agencies');
   
$idtoname = Array(); $idtoname = Array();
foreach ($agenciesdb->get_view("app", "byCanonicalName")->rows as $row) { foreach ($agenciesdb->get_view("app", "byCanonicalName")->rows as $row) {
$idtoname[$row->id] = trim($row->value->name); $idtoname[$row->id] = trim($row->value->name);
} }
$foidocsdb = $server->get_db('disclosr-foidocuments'); $foidocsdb = $server->get_db('disclosr-foidocuments');
try { try {
$rows = $foidocsdb->get_view("app", "byDate", Array('9999-99-99','0000-00-00'), true)->rows; $rows = $foidocsdb->get_view("app", "byDate", Array('9999-99-99','0000-00-00'), true)->rows;
   
   
if ($rows) { if ($rows) {
foreach ($rows as $row) { foreach ($rows as $row) {
displayLogEntry($row,$idtoname); echo displayLogEntry($row,$idtoname);
} }
} }
} catch (SetteeRestClientException $e) { } catch (SetteeRestClientException $e) {
setteErrorHandler($e); setteErrorHandler($e);
} }
include_footer_documents(); include_footer_documents();
?> ?>
   
# www.robotstxt.org/ # www.robotstxt.org/
# http://code.google.com/web/controlcrawlindex/ # http://code.google.com/web/controlcrawlindex/
   
User-agent: * User-agent: *
  Disallow: /admin/
  Sitemap: http://disclosurelo.gs/sitemap.xml.php
<?php <?php
   
// Agency X updated Y, new files, diff of plain text/link text, // Agency X updated Y, new files, diff of plain text/link text,
// feed for just one agency or all // feed for just one agency or all
// This is a minimum example of using the Universal Feed Generator Class // This is a minimum example of using the Universal Feed Generator Class
include("lib/FeedWriter.php"); include("../lib/FeedWriter/FeedTypes.php");
  include_once('../include/common.inc.php');
//Creating an instance of FeedWriter class. //Creating an instance of FeedWriter class.
$TestFeed = new FeedWriter(RSS2); $TestFeed = new RSS2FeedWriter();
//Setting the channel elements //Setting the channel elements
//Use wrapper functions for common channelelements //Use wrapper functions for common channelelements
$TestFeed->setTitle('Last Modified - All'); $TestFeed->setTitle('Last Modified - All');
$TestFeed->setLink('http://disclosr.lambdacomplex.org/rss.xml.php'); $TestFeed->setLink('http://disclosurelo.gs/rss.xml.php');
$TestFeed->setDescription('This is test of creating a RSS 2.0 feed Universal Feed Writer'); $TestFeed->setDescription('This is test of creating a RSS 2.0 feed Universal Feed Writer');
  $TestFeed->setChannelElement('language', 'en-us');
  $TestFeed->setChannelElement('pubDate', date(DATE_RSS, time()));
//Retriving informations from database //Retriving informations from database
$rows = $db->get_view("app", "byLastModified")->rows; $idtoname = Array();
  $agenciesdb = $server->get_db('disclosr-agencies');
  foreach ($agenciesdb->get_view("app", "byCanonicalName")->rows as $row) {
  $idtoname[$row->id] = trim($row->value->name);
  }
  $foidocsdb = $server->get_db('disclosr-foidocuments');
  $rows = $foidocsdb->get_view("app", "byDate", Array('9999-99-99','0000-00-00'), true)->rows;
//print_r($rows); //print_r($rows);
foreach ($rows as $row) { foreach ($rows as $row) {
//Create an empty FeedItem //Create an empty FeedItem
$newItem = $TestFeed->createNewItem(); $newItem = $TestFeed->createNewItem();
//Add elements to the feed item //Add elements to the feed item
$newItem->setTitle($row['name']); $newItem->setTitle($row->value->title);
$newItem->setLink($row['id']); $newItem->setLink("view.php?id=".$row->value->docID);
$newItem->setDate(date("c", $row['metadata']['lastModified'])); $newItem->setDate(date("c", strtotime($row->value->date)));
$newItem->setDescription($row['name']); $newItem->setDescription(displayLogEntry($row,$idtoname));
  $newItem->addElement('guid', $row->value->_id,array('isPermaLink'=>'true'));
//Now add the feed item //Now add the feed item
$TestFeed->addItem($newItem); $TestFeed->addItem($newItem);
} }
//OK. Everything is done. Now genarate the feed. //OK. Everything is done. Now genarate the feed.
$TestFeed->genarateFeed(); $TestFeed->generateFeed();
?> ?>
  <?php
 
  include ('../include/common.inc.php');
  $last_updated = date('Y-m-d', @filemtime('cbrfeed.zip'));
  header("Content-Type: text/xml");
  echo "<?xml version='1.0' encoding='UTF-8'?>";
  echo '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">' . "\n";
  echo " <url><loc>" . local_url() . "index.php</loc><priority>1.0</priority></url>\n";
  foreach (scandir("./") as $file) {
  if (strpos($file, ".php") !== false && $file != "index.php" && $file != "sitemap.xml.php")
  echo " <url><loc>" . local_url() . "$file</loc><priority>0.6</priority></url>\n";
  }
 
  $db = $server->get_db('disclosr-foidocuments');
  try {
  $rows = $db->get_view("app", "all")->rows;
  foreach ($rows as $row) {
  echo '<url><loc>' . local_url() . 'view.php?id=' . $row->value->_id . "</loc><priority>0.3</priority></url>\n";
  }
  } catch (SetteeRestClientException $e) {
  setteErrorHandler($e);
  }
  echo '</urlset>';
  ?>
 
<?php <?php
   
function include_header_documents($title) { function include_header_documents($title) {
?> ?>
<!doctype html> <!doctype html>
<!-- paulirish.com/2008/conditional-stylesheets-vs-css-hacks-answer-neither/ --> <!-- paulirish.com/2008/conditional-stylesheets-vs-css-hacks-answer-neither/ -->
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="en"> <![endif]--> <!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="en"> <![endif]-->
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8" lang="en"> <![endif]--> <!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8" lang="en"> <![endif]-->
<!--[if IE 8]> <html class="no-js lt-ie9" lang="en"> <![endif]--> <!--[if IE 8]> <html class="no-js lt-ie9" lang="en"> <![endif]-->
<!-- Consider adding a manifest.appcache: h5bp.com/d/Offline --> <!-- Consider adding a manifest.appcache: h5bp.com/d/Offline -->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en"> <!--<![endif]--> <!--[if gt IE 8]><!--> <html class="no-js" lang="en"> <!--<![endif]-->
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
   
<!-- Use the .htaccess and remove these lines to avoid edge case issues. <!-- Use the .htaccess and remove these lines to avoid edge case issues.
More info: h5bp.com/i/378 --> More info: h5bp.com/i/378 -->
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
   
<title>Australian Disclosure Logs<?php if ($title != "") echo " - $title";?></title> <title>Australian Disclosure Logs<?php if ($title != "") echo " - $title";?></title>
<meta name="description" content=""> <meta name="description" content="">
   
<!-- Mobile viewport optimized: h5bp.com/viewport --> <!-- Mobile viewport optimized: h5bp.com/viewport -->
<meta name="viewport" content="width=device-width"> <meta name="viewport" content="width=device-width">
   
<!-- Place favicon.ico and apple-touch-icon.png in the root directory: mathiasbynens.be/notes/touch-icons --> <!-- Place favicon.ico and apple-touch-icon.png in the root directory: mathiasbynens.be/notes/touch-icons -->
<meta name="google-site-verification" content="jkknX5g2FCpQvrW030b1Nq2hyoa6mb3EDiA7kCoHNj8" /> <meta name="google-site-verification" content="jkknX5g2FCpQvrW030b1Nq2hyoa6mb3EDiA7kCoHNj8" />
   
<!-- Le styles --> <!-- Le styles -->
<link href="css/bootstrap.min.css" rel="stylesheet"> <link href="css/bootstrap.min.css" rel="stylesheet">
<style type="text/css"> <style type="text/css">
body { body {
padding-top: 60px; padding-top: 60px;
padding-bottom: 40px; padding-bottom: 40px;
} }
.sidebar-nav { .sidebar-nav {
padding: 9px 0; padding: 9px 0;
} }
</style> </style>
<link href="css/bootstrap-responsive.min.css" rel="stylesheet"> <link href="css/bootstrap-responsive.min.css" rel="stylesheet">
   
<!-- HTML5 shim, for IE6-8 support of HTML5 elements --> <!-- HTML5 shim, for IE6-8 support of HTML5 elements -->
<!--[if lt IE 9]> <!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script> <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]--> <![endif]-->
<!-- More ideas for your <head> here: h5bp.com/d/head-Tips --> <!-- More ideas for your <head> here: h5bp.com/d/head-Tips -->
   
<!-- All JavaScript at the bottom, except this Modernizr build. <!-- All JavaScript at the bottom, except this Modernizr build.
Modernizr enables HTML5 elements & feature detects for optimal performance. Modernizr enables HTML5 elements & feature detects for optimal performance.
Create your own custom Modernizr build: www.modernizr.com/download/ Create your own custom Modernizr build: www.modernizr.com/download/
<script src="js/libs/modernizr-2.5.3.min.js"></script>--> <script src="js/libs/modernizr-2.5.3.min.js"></script>-->
<script src="js/jquery.js"></script> <script src="js/jquery.js"></script>
<script type="text/javascript" src="js/flotr2.min.js"></script> <script type="text/javascript" src="js/flotr2.min.js"></script>
</head> </head>
<body> <body>
<div class="navbar navbar-inverse navbar-fixed-top"> <div class="navbar navbar-inverse navbar-fixed-top">
<div class="navbar-inner"> <div class="navbar-inner">
<div class="container-fluid"> <div class="container-fluid">
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse"> <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
<span class="icon-bar"></span> <span class="icon-bar"></span>
<span class="icon-bar"></span> <span class="icon-bar"></span>
<span class="icon-bar"></span> <span class="icon-bar"></span>
</a> </a>
<a class="brand" href="#">Australian Disclosure Logs</a> <a class="brand" href="#">Australian Disclosure Logs</a>
<div class="nav-collapse collapse"> <div class="nav-collapse collapse">
<p class="navbar-text pull-right"> <p class="navbar-text pull-right">
Check out our subsites on: Check out our subsites on:
<a href="http://orgs.disclosurelo.gs">Government Agencies</a> <a href="http://orgs.disclosurelo.gs">Government Agencies</a>
• <a href="http://lobbyists.disclosurelo.gs">Political Lobbyists</a> • <a href="http://lobbyists.disclosurelo.gs">Political Lobbyists</a>
• <a href="http://contracts.disclosurelo.gs">Government Contracts and Spending</a> • <a href="http://contracts.disclosurelo.gs">Government Contracts and Spending</a>
   
</p> </p>
<ul class="nav"> <ul class="nav">
<li><a href="index.php">Home</a></li> <li><a href="index.php">Home</a></li>
<li><a href="disclogsList.php">List of Disclosure Logs</a></li> <li><a href="disclogsList.php">List of Disclosure Logs</a></li>
<li><a href="about.php">About</a></li> <li><a href="about.php">About</a></li>
</ul> </ul>
</div><!--/.nav-collapse --> </div><!--/.nav-collapse -->
</div> </div>
</div> </div>
</div> </div>
<div class="container"> <div class="container">
<?php <?php
} }
function include_footer_documents() { function include_footer_documents() {
?> ?>
</div> <!-- /container --> </div> <!-- /container -->
<hr> <hr>
   
<footer> <footer>
<p>&copy; Company 2012</p> <p>&copy; Company 2012</p>
</footer> </footer>
<script type="text/javascript"> <script type="text/javascript">
   
var _gaq = _gaq || []; var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-12341040-4']); _gaq.push(['_setAccount', 'UA-12341040-4']);
_gaq.push(['_setDomainName', 'disclosurelo.gs']); _gaq.push(['_setDomainName', 'disclosurelo.gs']);
_gaq.push(['_setAllowLinker', true]); _gaq.push(['_setAllowLinker', true]);
_gaq.push(['_trackPageview']); _gaq.push(['_trackPageview']);
   
(function() { (function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})(); })();
   
</script> </script>
<!-- Le javascript <!-- Le javascript
================================================== --> ================================================== -->
<!-- Placed at the end of the document so the pages load faster --> <!-- Placed at the end of the document so the pages load faster -->
<!-- <!--
<script src="js/bootstrap-transition.js"></script> <script src="js/bootstrap-transition.js"></script>
<script src="js/bootstrap-alert.js"></script> <script src="js/bootstrap-alert.js"></script>
<script src="js/bootstrap-modal.js"></script> <script src="js/bootstrap-modal.js"></script>
<script src="js/bootstrap-dropdown.js"></script> <script src="js/bootstrap-dropdown.js"></script>
<script src="js/bootstrap-scrollspy.js"></script> <script src="js/bootstrap-scrollspy.js"></script>
<script src="js/bootstrap-tab.js"></script> <script src="js/bootstrap-tab.js"></script>
<script src="js/bootstrap-tooltip.js"></script> <script src="js/bootstrap-tooltip.js"></script>
<script src="js/bootstrap-popover.js"></script> <script src="js/bootstrap-popover.js"></script>
<script src="js/bootstrap-button.js"></script> <script src="js/bootstrap-button.js"></script>
<script src="js/bootstrap-collapse.js"></script> <script src="js/bootstrap-collapse.js"></script>
<script src="js/bootstrap-carousel.js"></script> <script src="js/bootstrap-carousel.js"></script>
<script src="js/bootstrap-typeahead.js"></script>--> <script src="js/bootstrap-typeahead.js"></script>-->
   
   
</body> </body>
</html> </html>
<?php <?php
} }
   
function displayLogEntry($row, $idtoname) { function displayLogEntry($row, $idtoname) {
echo "<div><h2>".$row->value->date.": ".$row->value->title." (".$idtoname[$row->value->agencyID].")</h2> <p>".str_replace("\n","<br>",$row->value->description); $result = "";
  $result .= "<div><h2>".$row->value->date.": ".$row->value->title." (".$idtoname[$row->value->agencyID].")</h2> <p>".str_replace("\n","<br>",$row->value->description);
if (isset($row->value->notes)) { if (isset($row->value->notes)) {
echo " <br>Note: ".$row->value->notes; $result .= " <br>Note: ".$row->value->notes;
} }
echo "</p>"; $result .= "</p>";
   
if (isset($row->value->links)){ if (isset($row->value->links)){
echo "<h3>Links/Documents</h3><ul>"; $result .= "<h3>Links/Documents</h3><ul>";
foreach ($row->value->links as $link) { foreach ($row->value->links as $link) {
echo "<li><a href='$link'>".$link."</a></li>"; $result .= "<li><a href='$link'>".$link."</a></li>";
} }
   
echo "</ul>"; $result .= "</ul>";
} }
echo "<small><A href='".$row->value->url."'>View original source...</a> ID: ".$row->value->docID."</small>"; $result .= "<small><A href='".$row->value->url."'>View original source...</a> ID: ".$row->value->docID."</small>";
echo"</div>"; $result .= "</div>";
  return $result;
} }
   
  <?php
  include('template.inc.php');
  include_header_documents("");
  include_once('../include/common.inc.php');
  ?>
  <?php
 
 
 
  $agenciesdb = $server->get_db('disclosr-agencies');
 
  $idtoname = Array();
  foreach ($agenciesdb->get_view("app", "byCanonicalName")->rows as $row) {
  $idtoname[$row->id] = trim($row->value->name);
  }
  $foidocsdb = $server->get_db('disclosr-foidocuments');
  try {
  $obj = new stdClass();
  $obj->value = $foidocsdb->get($_REQUEST['id']);
  echo displayLogEntry($obj,$idtoname);
 
  } catch (SetteeRestClientException $e) {
  setteErrorHandler($e);
  }
  include_footer_documents();
  ?>
 
file:a/lib/FeedItem.php (deleted)
<?php  
/**  
* Univarsel Feed Writer  
*  
* FeedItem class - Used as feed element in FeedWriter class  
*  
* @package UnivarselFeedWriter  
* @author Anis uddin Ahmad <anisniit@gmail.com>  
* @link http://www.ajaxray.com/projects/rss  
*/  
class FeedItem  
{  
private $elements = array(); //Collection of feed elements  
private $version;  
 
/**  
* Constructor  
*  
* @param contant (RSS1/RSS2/ATOM) RSS2 is default.  
*/  
function __construct($version = RSS2)  
{  
$this->version = $version;  
}  
 
/**  
* Add an element to elements array  
*  
* @access public  
* @param srting The tag name of an element  
* @param srting The content of tag  
* @param array Attributes(if any) in 'attrName' => 'attrValue' format  
* @return void  
*/  
public function addElement($elementName, $content, $attributes = null)  
{  
$this->elements[$elementName]['name'] = $elementName;  
$this->elements[$elementName]['content'] = $content;  
$this->elements[$elementName]['attributes'] = $attributes;  
}  
 
/**  
* Set multiple feed elements from an array.  
* Elements which have attributes cannot be added by this method  
*  
* @access public  
* @param array array of elements in 'tagName' => 'tagContent' format.  
* @return void  
*/  
public function addElementArray($elementArray)  
{  
if(! is_array($elementArray)) return;  
foreach ($elementArray as $elementName => $content)  
{  
$this->addElement($elementName, $content);  
}  
}  
 
/**  
* Return the collection of elements in this feed item  
*  
* @access public  
* @return array  
*/  
public function getElements()  
{  
return $this->elements;  
}  
 
// Wrapper functions ------------------------------------------------------  
 
/**  
* Set the 'dscription' element of feed item  
*  
* @access public  
* @param string The content of 'description' element  
* @return void  
*/  
public function setDescription($description)  
{  
$tag = ($this->version == ATOM)? 'summary' : 'description';  
$this->addElement($tag, $description);  
}  
 
/**  
* @desc Set the 'title' element of feed item  
* @access public  
* @param string The content of 'title' element  
* @return void  
*/  
public function setTitle($title)  
{  
$this->addElement('title', $title);  
}  
 
/**  
* Set the 'date' element of feed item  
*  
* @access public  
* @param string The content of 'date' element  
* @return void  
*/  
public function setDate($date)  
{  
if(! is_numeric($date))  
{  
$date = strtotime($date);  
}  
 
if($this->version == ATOM)  
{  
$tag = 'updated';  
$value = date(DATE_ATOM, $date);  
}  
elseif($this->version == RSS2)  
{  
$tag = 'pubDate';  
$value = date(DATE_RSS, $date);  
}  
else  
{  
$tag = 'dc:date';  
$value = date("Y-m-d", $date);  
}  
 
$this->addElement($tag, $value);  
}  
 
/**  
* Set the 'link' element of feed item  
*  
* @access public  
* @param string The content of 'link' element  
* @return void  
*/  
public function setLink($link)  
{  
if($this->version == RSS2 || $this->version == RSS1)  
{  
$this->addElement('link', $link);  
}  
else  
{  
$this->addElement('link','',array('href'=>$link));  
$this->addElement('id', FeedWriter::uuid($link,'urn:uuid:'));  
}  
 
}  
 
/**  
* Set the 'encloser' element of feed item  
* For RSS 2.0 only  
*  
* @access public  
* @param string The url attribute of encloser tag  
* @param string The length attribute of encloser tag  
* @param string The type attribute of encloser tag  
* @return void  
*/  
public function setEncloser($url, $length, $type)  
{  
$attributes = array('url'=>$url, 'length'=>$length, 'type'=>$type);  
$this->addElement('enclosure','',$attributes);  
}  
 
} // end of class FeedItem  
?>  
 
file:a/lib/FeedWriter.php (deleted)
<?php  
// RSS 0.90 Officially obsoleted by 1.0  
// RSS 0.91, 0.92, 0.93 and 0.94 Officially obsoleted by 2.0  
// So, define constants for RSS 1.0, RSS 2.0 and ATOM  
 
define('RSS1', 'RSS 1.0', true);  
define('RSS2', 'RSS 2.0', true);  
define('ATOM', 'ATOM', true);  
 
/**  
* Univarsel Feed Writer class  
*  
* Genarate RSS 1.0, RSS2.0 and ATOM Feed  
*  
* @package UnivarselFeedWriter  
* @author Anis uddin Ahmad <anisniit@gmail.com>  
* @link http://www.ajaxray.com/projects/rss  
*/  
class FeedWriter  
{  
private $channels = array(); // Collection of channel elements  
private $items = array(); // Collection of items as object of FeedItem class.  
private $data = array(); // Store some other version wise data  
private $CDATAEncoding = array(); // The tag names which have to encoded as CDATA  
 
private $version = null;  
 
/**  
* Constructor  
*  
* @param constant the version constant (RSS1/RSS2/ATOM).  
*/  
function __construct($version = RSS2)  
{  
$this->version = $version;  
 
// Setting default value for assential channel elements  
$this->channels['title'] = $version . ' Feed';  
$this->channels['link'] = 'http://www.ajaxray.com/blog';  
 
//Tag names to encode in CDATA  
$this->CDATAEncoding = array('description', 'content:encoded', 'summary');  
}  
 
// Start # public functions ---------------------------------------------  
 
/**  
* Set a channel element  
* @access public  
* @param srting name of the channel tag  
* @param string content of the channel tag  
* @return void  
*/  
public function setChannelElement($elementName, $content)  
{  
$this->channels[$elementName] = $content ;  
}  
 
/**  
* Set multiple channel elements from an array. Array elements  
* should be 'channelName' => 'channelContent' format.  
*  
* @access public  
* @param array array of channels  
* @return void  
*/  
public function setChannelElementsFromArray($elementArray)  
{  
if(! is_array($elementArray)) return;  
foreach ($elementArray as $elementName => $content)  
{  
$this->setChannelElement($elementName, $content);  
}  
}  
 
/**  
* Genarate the actual RSS/ATOM file  
*  
* @access public  
* @return void  
*/  
public function genarateFeed()  
{  
header("Content-type: text/xml");  
 
$this->printHead();  
$this->printChannels();  
$this->printItems();  
$this->printTale();  
}  
 
/**  
* Create a new FeedItem.  
*  
* @access public  
* @return object instance of FeedItem class  
*/  
public function createNewItem()  
{  
$Item = new FeedItem($this->version);  
return $Item;  
}  
 
/**  
* Add a FeedItem to the main class  
*  
* @access public  
* @param object instance of FeedItem class  
* @return void  
*/  
public function addItem($feedItem)  
{  
$this->items[] = $feedItem;  
}  
 
 
// Wrapper functions -------------------------------------------------------------------  
 
/**  
* Set the 'title' channel element  
*  
* @access public  
* @param srting value of 'title' channel tag  
* @return void  
*/  
public function setTitle($title)  
{  
$this->setChannelElement('title', $title);  
}  
 
/**  
* Set the 'description' channel element  
*  
* @access public  
* @param srting value of 'description' channel tag  
* @return void  
*/  
public function setDescription($desciption)  
{  
$this->setChannelElement('description', $desciption);  
}  
 
/**  
* Set the 'link' channel element  
*  
* @access public  
* @param srting value of 'link' channel tag  
* @return void  
*/  
public function setLink($link)  
{  
$this->setChannelElement('link', $link);  
}  
 
/**  
* Set the 'image' channel element  
*  
* @access public  
* @param srting title of image  
* @param srting link url of the imahe  
* @param srting path url of the image  
* @return void  
*/  
public function setImage($title, $link, $url)  
{  
$this->setChannelElement('image', array('title'=>$title, 'link'=>$link, 'url'=>$url));  
}  
 
/**  
* Set the 'about' channel element. Only for RSS 1.0  
*  
* @access public  
* @param srting value of 'about' channel tag  
* @return void  
*/  
public function setChannelAbout($url)  
{  
$this->data['ChannelAbout'] = $url;  
}  
 
/**  
* Genarates an UUID  
* @author Anis uddin Ahmad <admin@ajaxray.com>  
* @param string an optional prefix  
* @return string the formated uuid  
*/  
public function uuid($key = null, $prefix = '')  
{  
$key = ($key == null)? uniqid(rand()) : $key;  
$chars = md5($key);  
$uuid = substr($chars,0,8) . '-';  
$uuid .= substr($chars,8,4) . '-';  
$uuid .= substr($chars,12,4) . '-';  
$uuid .= substr($chars,16,4) . '-';  
$uuid .= substr($chars,20,12);  
 
return $prefix . $uuid;  
}  
// End # public functions ----------------------------------------------  
 
// Start # private functions ----------------------------------------------  
 
/**  
* Prints the xml and rss namespace  
*  
* @access private  
* @return void  
*/  
private function printHead()  
{  
$out = '<?xml version="1.0" encoding="utf-8"?>' . "\n";  
 
if($this->version == RSS2)  
{  
$out .= '<rss version="2.0"  
xmlns:content="http://purl.org/rss/1.0/modules/content/"  
xmlns:wfw="http://wellformedweb.org/CommentAPI/"  
>' . PHP_EOL;  
}  
elseif($this->version == RSS1)  
{  
$out .= '<rdf:RDF  
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"  
xmlns="http://purl.org/rss/1.0/"  
xmlns:dc="http://purl.org/dc/elements/1.1/"  
>' . PHP_EOL;;  
}  
else if($this->version == ATOM)  
{  
$out .= '<feed xmlns="http://www.w3.org/2005/Atom">' . PHP_EOL;;  
}  
echo $out;  
}  
 
/**  
* Closes the open tags at the end of file  
*  
* @access private  
* @return void  
*/  
private function printTale()  
{  
if($this->version == RSS2)  
{  
echo '</channel>' . PHP_EOL . '</rss>';  
}  
elseif($this->version == RSS1)  
{  
echo '</rdf:RDF>';  
}  
else if($this->version == ATOM)  
{  
echo '</feed>';  
}  
 
}  
 
/**  
* Creates a single node as xml format  
*  
* @access private  
* @param srting name of the tag  
* @param mixed tag value as string or array of nested tags in 'tagName' => 'tagValue' format  
* @param array Attributes(if any) in 'attrName' => 'attrValue' format  
* @return string formatted xml tag  
*/  
private function makeNode($tagName, $tagContent, $attributes = null)  
{  
$nodeText = '';  
$attrText = '';  
 
if(is_array($attributes))  
{  
foreach ($attributes as $key => $value)  
{  
$attrText .= " $key=\"$value\" ";  
}  
}  
 
if(is_array($tagContent) && $this->version == RSS1)  
{  
$attrText = ' rdf:parseType="Resource"';  
}  
 
 
$attrText .= (in_array($tagName, $this->CDATAEncoding) && $this->version == ATOM)? ' type="html" ' : '';  
$nodeText .= (in_array($tagName, $this->CDATAEncoding))? "<{$tagName}{$attrText}><![CDATA[" : "<{$tagName}{$attrText}>";  
 
if(is_array($tagContent))  
{  
foreach ($tagContent as $key => $value)  
{  
$nodeText .= $this->makeNode($key, $value);  
}  
}  
else  
{  
$nodeText .= (in_array($tagName, $this->CDATAEncoding))? $tagContent : htmlentities($tagContent);  
}  
 
$nodeText .= (in_array($tagName, $this->CDATAEncoding))? "]]></$tagName>" : "</$tagName>";  
 
return $nodeText . PHP_EOL;  
}  
 
/**  
* @desc Print channels  
* @access private  
* @return void  
*/  
private function printChannels()  
{  
//Start channel tag  
switch ($this->version)  
{  
case RSS2:  
echo '<channel>' . PHP_EOL;  
break;  
case RSS1:  
echo (isset($this->data['ChannelAbout']))? "<channel rdf:about=\"{$this->data['ChannelAbout']}\">" : "<channel rdf:about=\"{$this->channels['link']}\">";  
break;  
}  
 
//Print Items of channel  
foreach ($this->channels as $key => $value)  
{  
if($this->version == ATOM && $key == 'link')  
{  
// ATOM prints link element as href attribute  
echo $this->makeNode($key,'',array('href'=>$value));  
//Add the id for ATOM  
echo $this->makeNode('id',$this->uuid($value,'urn:uuid:'));  
}  
else  
{  
echo $this->makeNode($key, $value);  
}  
 
}  
 
//RSS 1.0 have special tag <rdf:Seq> with channel  
if($this->version == RSS1)  
{  
echo "<items>" . PHP_EOL . "<rdf:Seq>" . PHP_EOL;  
foreach ($this->items as $item)  
{  
$thisItems = $item->getElements();  
echo "<rdf:li resource=\"{$thisItems['link']['content']}\"/>" . PHP_EOL;  
}  
echo "</rdf:Seq>" . PHP_EOL . "</items>" . PHP_EOL . "</channel>" . PHP_EOL;  
}  
}  
 
/**  
* Prints formatted feed items  
*  
* @access private  
* @return void  
*/  
private function printItems()  
{  
foreach ($this->items as $item)  
{  
$thisItems = $item->getElements();  
 
//the argument is printed as rdf:about attribute of item in rss 1.0  
echo $this->startItem($thisItems['link']['content']);  
 
foreach ($thisItems as $feedItem )  
{  
echo $this->makeNode($feedItem['name'], $feedItem['content'], $feedItem['attributes']);  
}  
echo $this->endItem();  
}  
}  
 
/**  
* Make the starting tag of channels  
*  
* @access private  
* @param srting The vale of about tag which is used for only RSS 1.0  
* @return void  
*/  
private function startItem($about = false)  
{  
if($this->version == RSS2)  
{  
echo '<item>' . PHP_EOL;  
}  
elseif($this->version == RSS1)  
{  
if($about)  
{  
echo "<item rdf:about=\"$about\">" . PHP_EOL;  
}  
else  
{  
die('link element is not set .\n It\'s required for RSS 1.0 to be used as about attribute of item');  
}  
}  
else if($this->version == ATOM)  
{  
echo "<entry>" . PHP_EOL;  
}  
}  
 
/**  
* Closes feed item tag  
*  
* @access private  
* @return void  
*/  
private function endItem()  
{  
if($this->version == RSS2 || $this->version == RSS1)  
{  
echo '</item>' . PHP_EOL;  
}  
else if($this->version == ATOM)  
{  
echo "</entry>" . PHP_EOL;  
}  
}  
 
 
 
// End # private functions ----------------------------------------------  
 
} // end of class FeedWriter  
 
// autoload classes  
function __autoload($class_name)  
{  
require_once $class_name . '.php';  
}