<?php
/**
 * ###############################################
 *
 * SWIFT Framework
 * _______________________________________________
 *
 * @author		Varun Shoor
 *
 * @package		SWIFT
 * @copyright	Copyright (c) 2001-2012, Kayako
 * @license		http://www.kayako.com/license
 * @link		http://www.kayako.com
 *
 * ###############################################
 */

/**
 * The News Synchronization Manager
 *
 * @author Varun Shoor
 */
class SWIFT_NewsSyncManager extends SWIFT_Library
{
	/**
	 * Constructor
	 *
	 * @author Varun Shoor
	 * @return bool "true" on Success, "false" otherwise
	 */
	public function __construct()
	{
		parent::__construct();

		return true;
	}

	/**
	 * Destructor
	 *
	 * @author Varun Shoor
	 * @return bool "true" on Success, "false" otherwise
	 */
	public function __destruct()
	{
		parent::__destruct();

		return true;
	}

	/**
	 * Sync with the given feed URL
	 *
	 * @author Varun Shoor
	 * @param string $_feedURL The Feed URL
	 * @param constant $_newsType The News Type
	 * @return bool "true" on Success, "false" otherwise
	 * @throws SWIFT_Exception If the Class is not Loaded
	 */
	public function Sync($_feedURL, $_newsType)
	{
		if (!$this->GetIsClassLoaded())
		{
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		}

		$_context = stream_context_create(array(
			'http' => array(
				'header' => 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:6.0.2) Gecko/20100101 Firefox/6.0.2'
			)
		));

		$_feedContents = file_get_contents($_feedURL, false, $_context);

		if (empty($_feedContents))
		{
			return false;
		}

		if(mb_detect_encoding($_feedContents) != 'UTF-8')
		{
			$_feedContents = utf8_encode($_feedContents);
		}

		$_XMLObject = simplexml_load_string($_feedContents);

		if (!isset($_XMLObject->channel) || !isset($_XMLObject->channel->item))
		{
			return false;
		}


		$_FeedObject = $this->ParseXMLFeed($_XMLObject);
		if (!isset($_FeedObject->items))
		{
			return false;
		}

		$_guidHashList = array();
		foreach ($_FeedObject->items as $_ItemObject)
		{
			$_guidHashList[] = md5((string) $_ItemObject->options->guid);
		}

		// Get list of sync'ed guids
		$_dbGuidHashList = $_dbGuidHashMap = array();
		$this->Database->Query("SELECT newsitemid, syncguidhash, contentshash, subjecthash, descriptionhash FROM " . TABLE_PREFIX . "newsitems WHERE issynced = '1' AND syncguidhash IN (" . BuildIN($_guidHashList) . ")");
		while ($this->Database->NextRecord())
		{
			$_dbGuidHashList[] = $this->Database->Record['syncguidhash'];
			$_dbGuidHashMap[$this->Database->Record['syncguidhash']] = array();
			$_dbGuidHashMap[$this->Database->Record['syncguidhash']]['newsitemid'] = $this->Database->Record['newsitemid'];
			$_dbGuidHashMap[$this->Database->Record['syncguidhash']]['contentshash'] = $this->Database->Record['contentshash'];
			$_dbGuidHashMap[$this->Database->Record['syncguidhash']]['subjecthash'] = $this->Database->Record['subjecthash'];
			$_dbGuidHashMap[$this->Database->Record['syncguidhash']]['descriptionhash'] = $this->Database->Record['descriptionhash'];
		}

		foreach ($_FeedObject->items as $_ItemObject)
		{
			$_guidHash = md5((string) $_ItemObject->options->guid);

			// Item is already in database
			if (in_array($_guidHash, $_dbGuidHashList))
			{
				$_newsItemID = $_dbGuidHashMap[$_guidHash]['newsitemid'];
				$_contentsHash = $_dbGuidHashMap[$_guidHash]['contentshash'];
				$_subjectHash = $_dbGuidHashMap[$_guidHash]['subjecthash'];
				$_descriptionHash = $_dbGuidHashMap[$_guidHash]['descriptionhash'];

				if (md5($_ItemObject->contents) != $_contentsHash || md5($_ItemObject->title) != $_subjectHash || md5($_ItemObject->description) != $_descriptionHash)
				{
					$_SWIFT_NewsItemObject = new SWIFT_NewsItem($_newsItemID);
					if ($_SWIFT_NewsItemObject instanceof SWIFT_NewsItem && $_SWIFT_NewsItemObject->GetIsClassLoaded())
					{
						$_SWIFT_NewsItemObject->UpdateContents($_ItemObject->title, $_ItemObject->description, $_ItemObject->contents);
					}
				}
			} else {
				$_newsItemID = SWIFT_NewsItem::Create($_newsType, SWIFT_NewsItem::STATUS_PUBLISHED, $_ItemObject->options->author, '', $_ItemObject->title, $_ItemObject->description,
						$_ItemObject->contents, false, false, true, false, array(), false, array(), true, $_ItemObject->options->guid, $_ItemObject->title, $_ItemObject->options->timestamp);

				$_categoryList = array();
				if (isset($_ItemObject->options->tags))
				{
					foreach ($_ItemObject->options->tags as $_TagObject)
					{
						$_categoryList[] = (string) $_TagObject;
					}
				}

				if (count($_categoryList))
				{
					$_visibilityType = SWIFT_PUBLIC;
					if ($_newsType == SWIFT_NewsItem::TYPE_PRIVATE)
					{
						$_visibilityType = SWIFT_PRIVATE;
					}

					SWIFT_NewsCategory::CreateOrUpdateFromSync($_categoryList, $_newsItemID, $_visibilityType);
				}
			}
		}

		return true;
	}


	/**
	 * Parse the XML Feed
	 *
	 * @author http://drupal.org/node/327508
	 * @param string $_feed_XML The Feed XML
	 * @return bool "true" on Success, "false" otherwise
	 * @throws SWIFT_Exception If the Class is not Loaded
	 */
	protected function ParseXMLFeed($feed_XML) {
	  $parsed_source = new stdClass();
	  // Detect the title.
	  $parsed_source->title = '';
	  if (isset($feed_XML->channel->title))
	  {
		  $parsed_source->title = (string) $feed_XML->channel->title;
	  }

	  // Detect the description.
	  $parsed_source->description = isset($feed_XML->channel->description) ? "{$feed_XML->channel->description}" : "";
	  $parsed_source->options = new stdClass();
	  // Detect the link.
	  $parsed_source->options->link = isset($feed_XML->channel->link) ? "{$feed_XML->channel->link}" : "";
	  $parsed_source->items = array();
	  $nslist = $feed_XML->getDocNamespaces(TRUE); // Armando

	  foreach ($feed_XML->xpath('//item') as $news) {
		$category = $news->xpath('category');
		$content = array();
		$dc = array();

		// Get children for current namespace.
		if (version_compare(phpversion(), '5.1.2', '>')) {
		  $content = (array)$news->children('http://purl.org/rss/1.0/modules/content/');
		  $dc = (array)$news->children('http://purl.org/dc/elements/1.1/');
		}
		///// Armando
		$nsinfo = array();
		foreach ($nslist as $nsname => $uri) {
			$nsinfo[$nsname] =  (array)$news->children($uri);
		}
		//////

		$news = (array) $news;
		$news['category'] = $category;

		$guid = $news['link'];
		if (isset($news['guid'])) {
		  $guid = $news['guid'];
		}

		$title = '';
		if (isset($news['title'])) {
		  $title = "{$news['title']}";
		}

		$body = $contents = '';
		if (isset($news['description'])) {
		  $body = (string) $news['description'];

		} elseif (isset($news['encoded'])) {  // content:encoded for PHP < 5.1.2.
		  $body = (string) $news['encoded'];
		} elseif (isset($content['encoded'])) { // content:encoded for PHP >= 5.1.2.
		  $body = (string) $content['encoded'];
		} else {
		  $body = (string) $news['title'];
		}

		if (isset($news['encoded'])) {  // content:encoded for PHP < 5.1.2.
		  $contents = (string) $news['encoded'];
		} elseif (isset($content['encoded'])) { // content:encoded for PHP >= 5.1.2.
		  $contents = (string) $content['encoded'];
		} else {
		  $contents = $body;
		}

		$author = '';
		if (isset($dc['creator']))
		{
			$author = $dc['creator'];
		} else if (isset($news['author'])) {
			$author = (string) $news['author'];
		}

		$original_author = $original_url = '';
		if (!empty($feed_XML->channel->title)) {
		  $original_author = (string) $feed_XML->channel->title;
		}

		if (!empty($news['link'])) {
		  $original_url = (string) $news['link'];
		}

		$additional_taxonomies = array();
		$additional_taxonomies['RSS Categories'] = array();
		$additional_taxonomies['RSS Domains'] = array();
		if (isset($news['category'])) {
		  foreach ($news['category'] as $category) {
			$additional_taxonomies['RSS Categories'][] = $category;
			if (isset($category['domain'])) {
			  $domain = (string)$category['domain'];
			  if (!empty($domain)) {
				  if (!isset($additional_taxonomies['RSS Domains'][$domain])) {
					$additional_taxonomies['RSS Domains'][$domain] = array();
				  }
				  $additional_taxonomies['RSS Domains'][$domain][] = count($additional_taxonomies['RSS Categories']) - 1;
			  }
			}
		  }
		}

		$_newsDate = '';
		if (isset($news['pubDate'])) {
			$_newsDate = $news['pubDate'];
		} else if (isset($dc['date'])) {
			$_newsDate = $dc['date'];
		}

		$item = new stdClass();
		$item->title = $title;
		$item->description = $body;
		$item->contents = $contents;
		$item->options = new stdClass();
		$item->options->author = $author;
		$item->options->original_author = $original_author;
		$item->options->timestamp = strtotime($_newsDate);
		$item->options->original_url = $original_url;
		$item->options->guid = $guid;
		$item->options->domains = $additional_taxonomies['RSS Domains'];
		$item->options->tags = $additional_taxonomies['RSS Categories'];
		$item->options->namespaces = $nsinfo; // Armando
		$parsed_source->items[] = $item;
	  }
	  return $parsed_source;
	}
}
?>