Home > PHP > class Syndication

class Syndication

December 19, 2009

Notice: This class is subject to change.

interface ISyndication:

<?php

interface ISyndication
{
	function GetBaseTags();
	function GetTitles( $maxLimit );
	function GetEntries( $maxLimit );
}

?>

class FeedReaderBase:

The base class for parsing xml feeds.


<?php

	require_once __DIR__.DIRECTORY_SEPARATOR.'interface.isyndication.php';
/**
 * class FeedReaderBase
 *
 * The base class for parsing xml feeds.
 *
 * @author     	Costin Trifan 
 * @copyright  	2009 Costin Trifan
 * @licence    	MIT License:	http://en.wikipedia.org/wiki/MIT_License
 * @last update	Dec. 2009
 * @version    	1.0
 */
class FeedReaderBase implements ISyndication
{
	private function __clone(){}
	private function __sleep(){}
	private function __wakeup(){}

	final public function __get( $name ) { throw new Exception('Method: "__get" is not allowed in class: '.__CLASS__); }
	final public function __set( $name, $value ) { throw new Exception('Method: "__set" is not allowed in class: '.__CLASS__); }

	/*[[ MUST OVERRIDE ]]*/
	public function GetBaseTags(){}
	public function GetTitles( $maxLimit ){}
	public function GetEntries( $maxLimit ){}
}
/*[ end class ]*/

?>

class AtomReader:

The base class for retrieving the content of an ATOM 2.0 feed.


<?php
	require_once __DIR__.DIRECTORY_SEPARATOR.'class.feedreaderbase.php';

/**
 * class AtomReader
 *
 * The base class for retrieving the content of an ATOM 2.0 feed.
 *
 * @author     	Costin Trifan 
 * @copyright  	2009 Costin Trifan
 * @licence    	MIT License:	http://en.wikipedia.org/wiki/MIT_License
 * @last update	Dec. 2009
 * @version    	1.0
 */
class AtomReader extends FeedReaderBase
{
	/**
	 * The instance of the DOMDocument class
	 *
	 * @see __construct
	 */
	protected $_doc = null;


	/**
	 * .ctor
	 */
	public function __construct( DOMDocument $docXML )
	{
		$this->_doc = $docXML;
	}


    /**
    * Retrieve the feed's base tags
	*
    * @return array
    */
    public function GetBaseTags()
    {
		parent::GetBaseTags();

        $result = array();

        $title = $this->_doc->getElementsByTagName('title')->item(0);
        if ( ! is_null($title))
            $result[$title->tagName] = $title->nodeValue;

        $subtitle = $this->_doc->getElementsByTagName('subtitle')->item(0);
        if ( ! is_null($subtitle))
            $result[$subtitle->tagName] = $subtitle->nodeValue;

        $link = $this->_doc->getElementsByTagName('link')->item(0);
        if ( ! is_null($link))
        {
            $result[$link->tagName] = $link->nodeValue;

            $result[$link->tagName] = array();
            $result[$link->tagName]['href'] = $link->getAttribute('href');
            $result[$link->tagName]['rel'] = $link->getAttribute('rel');
        }

        $updated = $this->_doc->getElementsByTagName('updated')->item(0);
        if ( ! is_null($updated))
            $result[$updated->tagName] = $updated->nodeValue;

        $author = $this->_doc->getElementsByTagName('author')->item(0);
        if ( ! is_null($author))
        {
            $result[$author->tagName] = array();

            if ( ! is_null($author->getElementsByTagName('name')->item(0)))
                $result[$author->tagName]['name'] = $author->getElementsByTagName('name')->item(0)->nodeValue;

            if ( ! is_null($author->getElementsByTagName('email')->item(0)))
                $result[$author->tagName]['email'] = $author->getElementsByTagName('email')->item(0)->nodeValue;
        }

        $id = $this->_doc->getElementsByTagName('id')->item(0);
        if ( ! is_null($id))
            $result[$id->tagName] = $id->nodeValue;

        return $result;
    } 


    /**
    * Retrieve the feed's titles
    *
    * @param int $maxLimit  The maximum number of titles to retrieve.
    * If $maxLimit = 0 all records will be retrieved.
	*
    * @return array
    */
	public function GetTitles( $maxLimit = 0 )
	{
		parent::GetTitles( $maxLimit );

        $result = array();

		$i = 0;
        foreach ($this->_doc->getElementsByTagName('entry') as $entry)
        {
			if ( ! is_null($entry->getElementsByTagName('title')->item(0)))
			{
				$title = $entry->getElementsByTagName('title')->item(0)->nodeValue;
				$title = html_entity_decode($title, ENT_QUOTES, 'UTF-8');

				$link = $entry->getElementsByTagName('link')->item(0)->getAttribute('href');
				$link = html_entity_decode($link, ENT_QUOTES, 'UTF-8');

				$result[$i]['title'] = $title;
				$result[$i]['link'] = $link;
			}
            $i++;
            if ($maxLimit == $i) break;
		}
        return $result;
	}


    /**
    * Retrieve the feed's entries
    *
    * @param int $maxLimit  The maximum number of entries to retrieve.
    * If $maxLimit = 0 all records will be retrieved.
	*
    * @return array
    */
    public function GetEntries( $maxLimit = 0 )
    {
		parent::GetEntries( $maxLimit );

        $result = array();

		$i = 0;
        foreach ($this->_doc->getElementsByTagName('entry') as $entry)
        {
            $result['entry_'.$i] = array();
            foreach ($entry->getElementsByTagName('*') as $tag)
                $result['entry_'.$i][$tag->tagName] = html_entity_decode($tag->nodeValue, ENT_QUOTES, 'UTF-8') ;

            if ( ! is_null($entry->getElementsByTagName('link')->item(0)))
                $result['entry_'.$i]['link'] = $entry->getElementsByTagName('link')->item(0)->getAttribute('href');

            $i++;
            if ($maxLimit == $i) break;
        }
        return $result;
    }

}
/*[ end class ]*/
?>

class RssReader:

The base class for retrieving the content of an RSS 2.0 feed.


<?php
	require_once __DIR__.DIRECTORY_SEPARATOR.'class.feedreaderbase.php';

/**
 * class RssReader
 *
 * The base class for retrieving the content of an RSS 2.0 feed.
 *
 * @author     	Costin Trifan 
 * @copyright  	2009 Costin Trifan
 * @licence    	MIT License:	http://en.wikipedia.org/wiki/MIT_License
 * @last update	Dec. 2009
 * @version    	1.0
 */
class RssReader extends FeedReaderBase
{
	/**
	 * The instance of the DOMDocument class
	 *
	 * @see __construct
	 */
	protected $_doc = null;


	/**
	 * .ctor
	 */
	public function __construct( DOMDocument $docXML )
	{
		$this->_doc = $docXML;
	}


    /**
    * Retrieve the feed's base tags
	*
    * @return array
    */
    public function GetBaseTags()
    {
		parent::GetBaseTags();

        $result = array();

        $ch = $this->_doc->getElementsByTagName('channel')->item(0);
        if ( ! is_null($ch))
        {
            if ($ch->hasChildNodes())
            {
                foreach ($ch->getElementsByTagName('*') as $tag)
                {
                    // do not select item tags
                    if ($tag->hasChildNodes() and ($tag->tagName  'item'))
                        $result[$tag->tagName] = html_entity_decode($tag->nodeValue, ENT_QUOTES, 'UTF-8') ;
                }
            }
        }
        return $result;
    } 


    /**
    * Retrieve the feed's titles
    *
    * @param int $maxLimit  The maximum number of titles to retrieve.
    * If $maxLimit = 0 all records will be retrieved.
	*
    * @return array
    */
	public function GetTitles( $maxLimit = 0 )
	{
		parent::GetTitles( $maxLimit );

        $result = array();

        $ch = $this->_doc->getElementsByTagName('channel')->item(0);
        if ( (! is_null($ch)) and $ch->hasChildNodes())
        {
			$i = 0;
			foreach ($ch->getElementsByTagName('item') as $tag)
			{
				if ( ! is_null($tag->getElementsByTagName('title')->item(0)))
				{
					$title = $tag->getElementsByTagName('title')->item(0)->nodeValue;
					$link = $tag->getElementsByTagName('link')->item(0)->nodeValue;

					$title = html_entity_decode($title, ENT_QUOTES, 'UTF-8');
					$link = html_entity_decode($link, ENT_QUOTES, 'UTF-8');

					$result[$i]['title'] = $title;
					$result[$i]['link'] = $link;
				}
				$i++;
				if ($maxLimit == $i) break;
			}
        }
        return $result;
	}


    /**
    * Retrieve the feed's entries
    *
    * @param int $maxLimit  The maximum number of entries to retrieve.
    * If $maxLimit = 0 all records will be retrieved.
	*
    * @return array
    */
    public function GetEntries( $maxLimit = 0 )
    {
		parent::GetEntries( $maxLimit );

        $result = array();

        $ch = $this->_doc->getElementsByTagName('channel')->item(0);
        if ( ! is_null($ch))
        {
            if ($ch->hasChildNodes())
            {
                $i = 0;
                foreach ($ch->getElementsByTagName('item') as $tag)
                {
                    $result['item_'.$i] = array();
                    
                    foreach ($tag->getElementsByTagName('*') as $item)
                        $result['item_'.$i][$item->tagName] = html_entity_decode($item->nodeValue, ENT_QUOTES, 'UTF-8') ;

                    $i++;
                    if ($maxLimit == $i) break;
                }
            }
        }
        return $result;
    } 

}
/*[ end class ]*/
?>

class Syndication:


<?php
/**
 * class Syndication
 *
 *
 * @author     	Costin Trifan 
 * @copyright  	2009 Costin Trifan
 * @licence    	MIT License:	http://en.wikipedia.org/wiki/MIT_License
 * @last update	Dec. 2009
 * @version    	1.0
 */
class Syndication
{
	private function __clone(){}
	private function __sleep(){}
	private function __wakeup(){}

	final public function __get( $name ) { throw new Exception('Method: "__get" is not allowed in class: '.__CLASS__); }
	final public function __set( $name, $value ) { throw new Exception('Method: "__set" is not allowed in class: '.__CLASS__); }

	/**
	* .ctor
	*/
	public function __construct() { }


/**
* PROPERTIES
*============================
*/
	protected $_type = null; 	/*[ Will hold the instances of the RSS or Atom class respectively ]*/

	protected $_doc = null;		/*[ The instance of the DOMDocument class ]*/

	private $_loaded = false; 	/*[ Whether or not the feed was successfully loaded ]*/


	/**
	 * Open the feed
	 *
	 * @param string $feed_url	The feed's url
	 * @throws Exception		If the xml document could not be opened
	 * @access private
	 * @return $this;
	 */
	public function Open( $feed_url )
	{
        $this->_doc = new DOMDocument();
        if ( @$this->_doc->load($feed_url) )
		{
            $this->_loaded = TRUE;
		}
        else { throw new Exception("The  {$feed_url}  file could not be opened!"); }
		
		$this->_loadClass();

		return $this;
	}


	/**
	* Check to see whether or not the xml document has been successfully loaded.
	*
	* @access public
	* @return bool
	*/
	public function IsLoaded()
	{
		return $this->_loaded;
	}


    /**
    * Retrieve the feed's base tags
	*
	* @access public
    * @return array
    */
	public function GetBaseTags( )
	{
		return $this->_type->GetBaseTags();
	}


    /**
    * Retrieve the feed's titles
    *
    * @param int $maxLimit  The maximum number of titles to retrieve.
    * If $maxLimit = 0 all records will be retrieved.
	*
	* @access public
    * @return array
    */
	public function GetTitles( $maxLimit )
	{
		return $this->_type->GetTitles( $maxLimit );
	}


    /**
    * Retrieve the feed's entries
    *
    * @param int $maxLimit  The maximum number of entries to retrieve.
    * If $maxLimit = 0 all records will be retrieved.
	*
	* @access public
    * @return array
    */
	public function GetEntries( $maxLimit )
	{
		return $this->_type->GetEntries( $maxLimit );
	}




	/**
	* Factory method. Check to see the feed's type and instantiate the appropriate class.
	*
	* @throws Exception		If one of the required classes was not found and if
	*						the type of the xml document is not a valid RSS or ATOM feed.
	* @access private
	* @return void
	*/
	private function _loadClass()
	{
		$root = $this->_doc->documentElement->tagName;

		if (strcasecmp($root, 'RSS') == 0)
		{
			@require __DIR__.DIRECTORY_SEPARATOR.'class.rss-reader.php';

			if (class_exists('RssReader')) { $this->_type = new RssReader( $this->_doc ); }
			else { throw new Exception('The class RssReader was not found!'); }
		}
		elseif (strcasecmp($root, 'FEED') == 0)
		{
			@require __DIR__.DIRECTORY_SEPARATOR.'class.atom-reader.php';

			if (class_exists('AtomReader')) { $this->_type = new AtomReader( $this->_doc ); }
			else { throw new Exception('The class AtomReader was not found!'); }
		}
		else { throw new Exception('Unsupported file format!'); }
	}

}
/*[ end class ]*/
?>

web.config.php file:

the app’s main configuration file.


<?php
	require 'web.settings.php';
	require 'class.syndication.php';
?>

web.functions.php file:

Holds the application’s global functions.


<?php
/**
*	GLOBAL FUNCTIONS
*=============================
*/

/**
* static class Fun
*
* Holds the global functions
*/
class Fun
{
	private function __clone(){}
	private function __sleep(){}
	private function __wakeup(){}
	private function __construct(){}

	final public function __get( $name ) { throw new Exception('Method: "__get" is not allowed in class: '.__CLASS__); }
	final public function __set( $name, $value ) { throw new Exception('Method: "__set" is not allowed in class: '.__CLASS__); }

/*[==================================================================================================================================]*/


	/**
	* Display feed's titles
	*
	*/
	public static function DisplayFeedTitles( Syndication $syn, $feed_url, $num_titles, $title_class )
	{
		$titles = ($syn->IsLoaded()) ? $syn->GetTitles($num_titles) : $syn->Open($feed_url)->GetTitles($num_titles);

		$data = '';
		foreach ($titles as $k)
		{
			$data .= '<h3 class="'.$title_class.'"><a href="'.$k['link'].'" title="'.$k['title'].'" target="_blank">'.$k['title'].'</a></h3>';
		}
		return $data;
	}

	/*[ etc... ]*/
}
/*[ end class ]*/
?>

web.settings.php file:

Holds the app’s settings.


<?php
/**
 *	SETTINGS FILE
 *==================================
 */



$dir_root = "D:/PHP_ROOT/rss_reader/";

$htpp_root = "http://localhost:8080/rss_reader/";

$bin_dir = $dir_root.'bin/';

?>

styles.css file:

Global stylesheet.


@import url("http://yui.yahooapis.com/2.8.0r4/build/reset/reset-min.css");


.FeedContainer {
	width: 200px; height: auto;
	margin: 25px;
	padding: 5px;
	background: #FFC;
	border: solid 1px #F90;
}

.FeedTitle { margin: 0 0 4px 0; }
.FeedTitle A { color: #036; text-decoration: none; font-family: inherit; font-size: inherit; }
.FeedTitle A:hover { color: #F00; text-decoration: none; }

index.php file:


<?php
	require 'bin/web.config.php';
	require 'bin/web.functions.php';

	$rss = 'https://incomod.wordpress.com/feed/';
	$atom = 'http://blogs.technet.com/msrc/atom.xml';

?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title></title>
	<link rel="stylesheet" type="text/css" href="resx/styles.css" media="screen" />
</head>
<body>

    <div class="FeedContainer">
	    <?php /*[ TODO: Enable cache. ]*/
			echo Fun::DisplayFeedTitles(new Syndication(), $rss, 5, 'FeedTitle');
		?>
    </div>

<br /><hr /><br />

    <div class="FeedContainer">
	    <?php /*[ TODO: Enable cache. ]*/
			echo Fun::DisplayFeedTitles(new Syndication(), $atom, 5, 'FeedTitle');
		?>
    </div>

</body>
</html>

Directory structure:

  • Root
    • bin
      • class.atom-reader.php
      • class.feedreaderbase.php
      • class.rss-reader.php
      • class.syndication.php
      • interface.isyndication.php
      • web.config.php
      • web.functions.php
      • web.settings.php
    • resx
      • styles.css
    • index.php
Advertisements
Categories: PHP Tags: ,
%d bloggers like this: