<?php
// $Id: build_rss.php,v 1.3 2006/09/29 12:39:36 ohwada Exp $

// 2006-09-20 K.OHWADA
// this is new file
// porting from rssc_build_base

//=========================================================
// Happy Linux Framework Module
// 2006-09-01 K.OHWADA
//=========================================================

//=========================================================
// class builder base
//=========================================================
class happy_linux_build_rss
{
// constant
	var $_MODULE_ID_DEFUALT = 1;
	var $_HEADER   = 'Content-Type:text/xml; charset=utf-8';
	var $_RSS_DOCS = 'http://backend.userland.com/rss/';

// flag
	var $_FLAG_UTF8_STRIP_CONTROL = true;

// class instance
	var $_system;
	var $_strings;
	var $_convert;

// http://web.resource.org/rss/1.0/spec#s5.5.3
// (Suggested) Maximum Length: 500
	var $_max_summary = 500;

// set param
	var $_channel = array();
	var $_items   = array();
	var $_cache_time  = 0;	// no cache
	var $_flag_force_build = false;
	var $_view_goto_title  = 'goto index';
	var $_view_goto_url    = null;

// local variable
	var $_count_line = 1;

// override
	var $_GENERATOR     = 'XOOPS Happy Linux';
	var $_GENERATOR_URI = 'http://linux2.ohwada.net/';
	var $_CATEGORY      = 'Happy Linux';
	var $_TITLE         = 'Feeds';
	var $_RDF_TITLE     = 'RDF Feeds';
	var $_RSS_TITLE     = 'RSS Feeds';
	var $_ATOM_TITLE    = 'ATOM Feeds';
	var $_TEMPLATE      = null;
	var $_RDF_TEMPLATE  = null;
	var $_RSS_TEMPLATE  = null;
	var $_ATOM_TEMPLATE = null;
	var $_MODE          = 'other';

//---------------------------------------------------------
// constructor
//---------------------------------------------------------
function happy_linux_build_rss()
{
// class instance
	$this->_system  =& happy_linux_system::getInstance();
	$this->_strings =& happy_linux_strings::getInstance();
	$this->_convert =& happy_linux_convert_encoding::getInstance();
}

function &getInstance()
{
	static $instance;
	if (!isset($instance)) 
	{
		$instance = new happy_linux_build_rss();
	}

	return $instance;
}


//=========================================================
// public
//=========================================================
function build()
{
// no output encode
	happy_linux_http_output('pass');

	header($this->_HEADER);

	$template = $this->_get_template();

	$tpl = new XoopsTpl();

// use cache
	if ( !$this->_flag_force_build && ($this->_cache_time > 0) )
	{
		$tpl->xoops_setCaching(2);
		$tpl->xoops_setCacheTime($this->_cache_time);
	}

// always build
	if ( $this->_flag_force_build || !$tpl->is_cached($template) || ($this->_cache_time == 0) ) 
	{
		$this->_assign( $tpl );
	}

	$tpl->display($template);
}

function view()
{
	header ('Content-Type:text/html; charset=utf-8');

	$template = $this->_get_template();
	if ( empty($template) )
	{
		echo "<font color='red'>No Template</font><br />\n";
		return;
	}

	$tpl = new XoopsTpl();

	$this->_assign( $tpl );

	$xml   = $tpl->fetch($template);
	$body  = $this->_strings->sanitize_textarea( $xml );
	$title = $this->_get_title();

?>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title><?php echo $title; ?></title>
</head>
<body>
<h3><?php echo $title; ?></h3>
This is debug mode <br /> <br />
<hr />
<pre>
<?php echo $body; ?>
</pre>
<hr />
<?php

	if ( $this->_view_goto_url && $this->_view_goto_title )
	{
		echo '<a href="'.$this->_view_goto_url.'">'.$this->_view_goto_title.'</a>'."\n";
	}

?>
</body>
</html>
<?php

}

function clear()
{
	$template = $this->_get_template();
	$tpl = new XoopsTpl();
	$tpl->clear_cache($template);
}

// --------------------------------------------------------
// set param
// --------------------------------------------------------
function set_cache_time($value)
{
	$this->_cache_time = intval($value);
}

function set_max_summary($value)
{
	$this->_max_summary = intval($value);
}

function set_channel($value)
{
	$this->_channel = $value;
}

function set_items($value)
{
	$this->_items = $value;
}

function set_flag_force_build($value)
{
	$this->_flag_force_build = (bool)$value;
}

function set_view_goto_title($value)
{
	$this->_view_goto_title = $value;
}

function set_view_goto_url($value)
{
	$this->_view_goto_url = $value;
}

function set_mode($val)
{
	switch ( $val )
	{
		case 'rdf':
		case 'atom':
		case 'rss':
			$this->_MODE = $val;
			break;

		default:
			$this->_MODE = 'other';
			break;
	}
}

function set_generator($value)
{
	$this->_GENERATOR = $value;
}

function set_generator_uri($value)
{
	$this->_GENERATOR_URI = $value;
}

function set_category($value)
{
	$this->_CATEGORY = $value;
}

function set_template($value)
{
	$this->_TEMPLATE = $value;
}

function set_rdf_template($value)
{
	$this->_RDF_TEMPLATE = $value;
}

function set_rss_template($value)
{
	$this->_RSS_TEMPLATE = $value;
}

function set_atom_template($value)
{
	$this->_ATOM_TEMPLATE = $value;
}

function set_title($value)
{
	$this->_TITLE = $value;
}

function set_rdf_title($value)
{
	$this->_RDF_TITLE = $value;
}

function set_rss_title($value)
{
	$this->_RSS_TITLE = $value;
}

function set_atom_title($value)
{
	$this->_ATOM_TITLE = $value;
}

//=========================================================
// private
//=========================================================
function _assign( &$tpl )
{
	switch ( $this->_MODE )
	{
		case 'rdf':
			$this->_assign_rdf( $tpl );
			break;

		case 'atom':
			$this->_assign_atom( $tpl );
			break;

		case 'rss':
			$this->_assign_rss( $tpl );
			break;

		case 'other':
		default:
			$this->_assign_other( $tpl );
			break;
	}
}

function _get_template()
{
	switch ( $this->_MODE )
	{
		case 'rdf':
			$ret = $this->_RDF_TEMPLATE;
			break;

		case 'atom':
			$ret = $this->_ATOM_TEMPLATE;
			break;

		case 'rss':
			$ret = $this->_RSS_TEMPLATE;
			break;

		case 'other';
		default:
			$ret = $this->_TEMPLATE;
			break;
	}
	return $ret;
}

function _get_title()
{
	switch ( $this->_MODE )
	{
		case 'rdf':
			$ret = $this->_RDF_TITLE;
			break;

		case 'atom':
			$ret = $this->_ATOM_TITLE;
			break;

		case 'rss':
		default:
			$ret = $this->_RSS_TITLE;
			break;
	}
	return $ret;
}

function _get_site_tag($url)
{
	$parse = parse_url($url);
	if ( isset($parse['host']) )
	{
		$ret = $parse['host'];
		return $ret;
	}
	return false;
}

// --------------------------------------------------------
// meke title
// --------------------------------------------------------
function _build_xml_title($title, $flag_char=1, $flag_numeric=1)
{
	if ($flag_char)
	{
		$title = $this->_strip_html_entity_char( $title );
	}

	if ($flag_numeric)
	{
		$title = $this->_strip_html_entity_numeric($title);
	}

	$title = $this->_xml_htmlspecialchars($title);

	return $title;
}

// --------------------------------------------------------
// meke content
// --------------------------------------------------------
function _build_xml_content($content, $flag_control=1, $flag_undo=1)
{
	if ($flag_control)
	{
		$content = $this->_strings->strip_control($content);
	}

	if ($flag_undo)
	{
		$content = $this->_undo_html_special_chars($content);
	}

// not sanitize
	$cont = $this->_convert_cdata($content);

	return $cont;
}

function _convert_cdata($text)
{
	$text = preg_replace("/]]>/", ']]&gt;', $text);
	return $text;
}

// --------------------------------------------------------
// meke summary
// --------------------------------------------------------
function _build_xml_summary($sum, $flag_char=1, $flag_numeric=1, $flag_control=1, $flag_undo=1, $flag_return=1, $flag_tab=1, $flag_style=1, $flag_space=1)
{
	if ($flag_char)
	{
		$sum = $this->_strip_html_entity_char($sum);
	}

	if ($flag_numeric)
	{
		$sum = $this->_strip_html_entity_numeric($sum);
	}

	if ($flag_control)
	{
		$sum = $this->_strings->strip_control($sum);
	}

	if ($flag_undo)
	{
		$sum = $this->_undo_html_special_chars($sum);
	}

	if ($flag_return)
	{
		$sum = $this->_strings->strip_return($sum);
	}

	if ($flag_tab)
	{
		$sum = $this->_strings->strip_tab($sum);
	}

	if ($flag_style)
	{
		$sum = $this->_strings->strip_style_tag($sum);
	}

	$sum = strip_tags($sum);

	if ($flag_space)
	{
		$sum = $this->_strings->strip_space($sum);
	}

	$sum = $this->_strings->shorten_text($sum, $this->_max_summary );
	$sum = $this->_xml_htmlspecialchars($sum);

	return $sum;
}

// --------------------------------------------------------
// htmlspecialchars
// http://www.w3.org/TR/REC-xml/#dt-markup
// http://www.fxis.co.jp/xmlcafe/tmp/rec-xml.html#dt-markup
//   &  -> &amp;	// without html entity
//   <  -> &lt;
//   >  -> &gt;
//   "  -> &quot;
//   '  -> &apos;
// --------------------------------------------------------
function _xml($text)
{
	$ret = $this->_xml_htmlspecialchars_strict($text);
	return $ret;
}

function _xml_url($text)
{
	$ret = $this->_xml_htmlspecialchars_url($text);
	return $ret;
}

function _xml_htmlspecialchars($text)
{
	$text = htmlspecialchars($text);
	$text = preg_replace("/'/", '&apos;', $text);
	return $text;
}

function _xml_htmlspecialchars_strict($text)
{
	$text = $this->_strip_html_entity_char($text);
	$text = $this->_xml_htmlspecialchars($text);
	return $text;
}

function _xml_htmlspecialchars_url($text)
{
	$text = preg_replace("/&amp;/sU", '&', $text);
	$text = $this->_strip_html_entity_char($text);
	$text = $this->_xml_htmlspecialchars($text);
	return $text;
}

// --------------------------------------------------------
// undo XOOPS HtmlSpecialChars
//   &lt;   -> <
//   &gt;   -> >
//   &quot; -> "
//   &#039; -> '
//   &amp;  -> &
//   &amp;nbsp; -> &nbsp;
// --------------------------------------------------------
function _undo_html_special_chars($text)
{
	$text = preg_replace("/&gt;/i",   '>', $text);
	$text = preg_replace("/&lt;/i",   '<', $text);
	$text = preg_replace("/&quot;/i", '"', $text);
	$text = preg_replace("/&#039;/i", "'", $text);	
	$text = preg_replace("/&amp;nbsp;/i", '&nbsp;', $text);
	return $text;
}

// --------------------------------------------------------
// undo html entities
//   &amp;abc;  -> &abc;
// --------------------------------------------------------
function _undo_html_entity_char($text)
{
	$ret = preg_replace("/&amp;([0-9a-zA-z]+);/sU", '&\\1;', $text);
	return $ret;
}

// --------------------------------------------------------
// undo html entities
//   &amp;#123; -> &#123;
// --------------------------------------------------------
function _undo_html_entity_numeric($text)
{
	$ret = preg_replace("/&amp;#([0-9a-fA-F]+);/sU", '&#\\1;', $text);
	return $ret;
}

// --------------------------------------------------------
// strip html entities
//   &abc; -> ' '
// --------------------------------------------------------
function _strip_html_entity_char($text)
{
	$ret = preg_replace("/&[0-9a-zA-z]+;/sU", ' ', $text);
	return $ret;
}

// --------------------------------------------------------
// strip html entities
//   &#123; -> ' '
// --------------------------------------------------------
function _strip_html_entity_numeric($text)
{
	$ret = preg_replace("/&amp;#([0-9a-fA-F]+);/sU", '&#\\1;', $text);
	return $ret;
}

//---------------------------------------------------------
// http://www.w3.org/TR/NOTE-datetime
// 2003-12-13T18:30:02+09:00
//
// http://www.php.net/manual/ja/function.date.php
// User Contributed Notes
//---------------------------------------------------------
function _iso8601_date($time)
{
	$tzd  = date('O',$time);
	$tzd  = substr( chunk_split( $tzd, 3, ':' ), 0, 6 );
	$date = date('Y-m-d\TH:i:s', $time) . $tzd;
	return $date;
}

//-----------------------------------------------
// use convert class
//-----------------------------------------------
function _utf8( $text )
{
	$ret = $this->_convet_to_utf8( $text );
	return $ret;
}

function _convet_to_utf8( $text )
{
	$text = $this->_convert->convert($text, 'utf-8', _CHARSET);

	if ( $this->_FLAG_UTF8_STRIP_CONTROL )
	{
		$text = $this->_strings->strip_control( $text );
	}

	return $text;
}

//=========================================================
// assign to template
//=========================================================

//---------------------------------------------------------
// http://web.resource.org/rss/1.0/spec
// required paramter
// channel elements 
//   - title
//   - link
// item elements
//   - title
//   - link
//---------------------------------------------------------
function _assign_rdf( &$tpl )
{
	$channel = $this->_build_rdf_channel();
	$items   = $this->_build_rdf_items();

	$tpl->assign('xml_lang',       $this->_utf8( $channel['xml_lang'] ) );
	$tpl->assign('channel_title',  $this->_utf8( $channel['title'] ) );
	$tpl->assign('channel_link',   $this->_utf8( $channel['link']  ));
	$tpl->assign('channel_description',  $this->_utf8( $channel['description']  ));
	$tpl->assign('channel_dc_language',  $this->_utf8( $channel['dc_language'] ) );
	$tpl->assign('channel_dc_date',      $this->_utf8( $channel['dc_date'] ) );

	foreach ($items as $item)
	{
		$tpl->append('items', 
			array(
				'link'        => $this->_utf8( $item['link'] ),
				'title'       => $this->_utf8( $item['title'] ),
				'description' => $this->_utf8( $item['description'] ),
				'dc_subject'  => $this->_utf8( $item['dc_subject'] ),
				'dc_creator'  => $this->_utf8( $item['dc_creator'] ), 
				'dc_date'     => $this->_utf8( $item['dc_date'] ), 
				'content_encoded' => $this->_utf8( $item['content_encoded'] ),
			));
	}

}

function _build_rdf_channel()
{
	$ret = $this->_build_common_channel();
	return $ret;
}

function _build_rdf_items()
{
	$arr = array();

	if ( is_array($this->_items) && count($this->_items) )
	{
		foreach ($this->_items as $item)
		{
			$arr[] = $this->_build_rdf_item( $item );
		}
	}

	return $arr;
}

//---------------------------------------------------------
// http://blogs.law.harvard.edu/tech/rss
// required paramter
// channel elements 
//   - title
//   - link
//   - description
// item elements
//   - title
//   - link
//   - description
//---------------------------------------------------------
function _assign_rss( &$tpl )
{
	$channel = $this->_build_rss_channel();
	$items   = $this->_build_rss_items();

	$tpl->assign('channel_title',      $this->_utf8( $channel['title'] ) );
	$tpl->assign('channel_link',       $this->_utf8( $channel['link']  ));
	$tpl->assign('channel_docs',       $this->_utf8( $channel['docs'] ) );
	$tpl->assign('channel_generator',  $this->_utf8( $channel['generator'] ) );
	$tpl->assign('channel_category',   $this->_utf8( $channel['category'] ) );
	$tpl->assign('channel_copyright',  $this->_utf8( $channel['copyright'] ) );
	$tpl->assign('channel_language',   $this->_utf8( $channel['language'] ) );
	$tpl->assign('channel_webmaster',  $this->_utf8( $channel['webmaster'] ) );
	$tpl->assign('channel_lastbuild',  $this->_utf8( $channel['lastbuild'] ) );
	$tpl->assign('channel_pubdate',    $this->_utf8( $channel['pubdate'] ) );
	$tpl->assign('channel_description',    $this->_utf8( $channel['description']  ));
	$tpl->assign('channel_managingeditor', $this->_utf8( $channel['managingeditor'] ) );

	$tpl->assign('image_url',    $this->_utf8( $channel['image_url'] ) );
	$tpl->assign('image_width',  $this->_utf8( $channel['image_width'] ) );
	$tpl->assign('image_height', $this->_utf8( $channel['image_height'] ) );
	$tpl->assign('image_title',  $this->_utf8( $channel['image_title']  ));
	$tpl->assign('image_link',   $this->_utf8( $channel['image_link'] ) );

	foreach ($items as $item)
	{
		$tpl->append('items', 
			array(
				'link'        => $this->_utf8( $item['link'] ),
				'guid'        => $this->_utf8( $item['guid'] ),
				'title'       => $this->_utf8( $item['title'] ),
				'description' => $this->_utf8( $item['description'] ),
				'category'    => $this->_utf8( $item['category'] ),
				'pubdate'     => $this->_utf8( $item['pubdate'] ), 

// for future
//				'dc_creator'      => $this->_utf8( $item['dc_creator'] ), 
//				'content_encoded' => $this->_utf8( $item['content_encoded'] ),
			));
	}

}

function _build_rss_channel()
{
	$channel = $this->_build_common_channel();

	$channel['pubdate'] = $channel['date_rfc822'];

// lastbuild
	$updated_unix = $this->_get_last_updated_unix( $this->_items );
	if ( $updated_unix )
	{
		$channel['lastbuild'] = date("r", $updated_unix );
	}
	else
	{
		$channel['lastbuild'] = '';
	}

	return $channel;
}

function _build_rss_items()
{
	$arr = array();

	if ( is_array($this->_items) && count($this->_items) )
	{
		foreach ($this->_items as $item)
		{
			$arr[] = $this->_build_rss_item( $item );
		}
	}

	return $arr;
}

//---------------------------------------------------------
// http://www.mnot.net/drafts/draft-nottingham-atom-format-02.html
// required paramter
// feed elements 
//   - id
//   - title
//   - updated
//   - author name
// entry elements 
//   - id
//   - title
//   - updated
//   - author name
//   - summary or content
//---------------------------------------------------------
function _assign_atom( &$tpl )
{
	$channel = $this->_build_atom_channel();
	$entrys  = $this->_build_atom_entrys();

	$tpl->assign('xml_lang',           $this->_utf8( $channel['xml_lang'] ) );
	$tpl->assign('feed_title',         $this->_utf8( $channel['title'] ) );
	$tpl->assign('feed_link_alt',      $this->_utf8( $channel['link_alt']  ));
	$tpl->assign('feed_link_self',     $this->_utf8( $channel['link_self'] ) );
	$tpl->assign('feed_id',            $this->_utf8( $channel['id'] ) );
	$tpl->assign('feed_generator',     $this->_utf8( $channel['generator'] ) );
	$tpl->assign('feed_generator_uri', $this->_utf8( $channel['generator_uri'] ) );
	$tpl->assign('feed_rights',        $this->_utf8( $channel['rights'] ) );
	$tpl->assign('feed_author_name',   $this->_utf8( $channel['author_name'] ) );
	$tpl->assign('feed_author_uri',    $this->_utf8( $channel['author_uri'] ) );
	$tpl->assign('feed_author_email',  $this->_utf8( $channel['author_email'] ) );
	$tpl->assign('feed_updated',       $this->_utf8( $channel['updated'] ) );

	foreach ($entrys as $entry)
	{
		$tpl->append('entrys', 
			array(
				'title'        => $this->_utf8( $entry['title'] ),
				'link'         => $this->_utf8( $entry['link'] ),
				'id'           => $this->_utf8( $entry['id'] ), 
				'summary'      => $this->_utf8( $entry['summary'] ),
				'category'     => $this->_utf8( $entry['category'] ),
				'content'      => $this->_utf8( $entry['content'] ),
				'author_name'  => $this->_utf8( $entry['author_name'] ),
				'author_uri'   => $this->_utf8( $entry['author_uri'] ),
				'author_email' => $this->_utf8( $entry['author_email'] ),
				'updated'      => $this->_utf8( $entry['updated'] ),
				'published'    => $this->_utf8( $entry['published'] ),
			));
	}
}

function _build_atom_channel()
{
	$channel = $this->_build_common_channel();

// atom id
	$site_id = "tag:".$this->_site_tag.",".$this->_site_year."://1";
	$channel['id'] = $this->_xml( $site_id );

// date
	$channel['updated'] = $channel['date_iso8601'];

	return $channel;
}

function _build_atom_entrys()
{
	$arr = array();
	$this->_count_line = 1;

	if ( is_array($this->_items) && count($this->_items) )
	{
		foreach ($this->_items as $entry)
		{
			$arr[] = $this->_build_atom_entry( $entry );
		}
	}

	return $arr;
}

//---------------------------------------------------------
// common
//---------------------------------------------------------
function _build_common_channel()
{

// site information
	$site_url          = XOOPS_URL.'/';
	$site_name         = $this->_system->get_sitename();
	$site_desc         = $this->_system->get_slogan();
	$site_author_name  = $this->_system->get_meta_author();
	$site_author_email = $this->_system->get_adminmail();
	$site_author_uri   = '';

	$site_link_self = 'http://'.$_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"];

	$site_url_xml          = $this->_xml_url( $site_url );
	$site_author_email_xml = $this->_xml( $site_author_email );
	$language_xml          = $this->_xml( _LANGCODE );

	$time             = time();
	$date_rfc822_xml  = $this->_xml( date("r", $time ) );
	$date_iso8601_xml = $this->_xml( $this->_iso8601_date( $time ) );

// image
	$site_image_url    = '';
	$site_image_link   = '';
	$site_image_width  = '';
	$site_image_height = '';
	$site_image_title  = '';

// copyright
	$year               = date("Y");
	$site_copyright     = "Copyright (c) $year, $site_author_name";
	$site_copyright_xml = $this->_xml( $site_copyright );

// save param
	$this->_site_author_name = $site_author_name;
	$this->_site_tag         = $this->_get_site_tag( $site_url );
	$this->_site_year        = $year;

	$ret = array(
		'link'           => $site_url_xml,
		'link_alt'       => $site_url_xml,
		'author_uri'     => $site_url_xml,
		'link_self'      => $this->_xml_url( $site_link_self ),
		'image_url'      => $this->_xml_url( $site_image_url ),
		'image_link'     => $this->_xml_url( $site_image_link ),
		'generator_uri'  => $this->_xml_url( $this->_GENERATOR_URI ),
		'language'       => $language_xml,
		'copyright'      => $site_copyright_xml,
		'rights'         => $site_copyright_xml,
		'author_email'   => $site_author_email_xml,
		'webmaster'      => $site_author_email_xml,
		'managingeditor' => $site_author_email_xml,
		'title'          => $this->_xml( $site_name ),
		'description'    => $this->_xml( $site_desc ),
		'generator'      => $this->_xml( $this->_GENERATOR ),
		'category'       => $this->_xml( $this->_CATEGORY ),
		'docs'           => $this->_xml( $this->_RSS_DOCS ),
		'author_name'    => $this->_xml( $site_author_name ),
		'author_uri'     => $this->_xml( $site_author_uri ),
		'image_width'    => $this->_xml( $site_image_width ),
		'image_height'   => $this->_xml( $site_image_height ),
		'image_title'    => $this->_xml( $site_image_title ),

		'date_unix'      => $time,
		'date_rfc822'    => $date_rfc822_xml,
		'date_iso8601'   => $date_iso8601_xml,

		'xml_lang'       => $language_xml,
		'dc_language'    => $language_xml,
		'dc_date'        => $date_iso8601_xml,
	);

	return $ret;
}

function _get_last_updated_unix( $items )
{
	$time = false;
	if ( isset($items[0]['updated_unix']) )
	{
		$time = $items[0]['updated_unix'];
	}
	return $time;
}

//=========================================================
// over ride
//=========================================================
function _assign_other( &$tpl )
{
	// dummy
}

function _build_rdf_item( $item )
{
	// dummy
}

function _build_rss_item( $item )
{
	// dummy
}

function _build_atomf_item( $item )
{
	// dummy
}

// --- class end ---
}

?>