Location: PHPKode > scripts > Ray Feed Reader > ray-feed-reader/rayfeedreader.php
<?php

    /**
     * RayFeedReader
     *
     * SimpleXML based feed reader class. A very specific feed reader designed
     * to working with no or little configurations.
     *
     * - This class can read an rss feed into array from a given url.
     * - Also can render html widget with plugable RayFeedWidget Class.
     * 
     * Supports following feed types:
     *  - RSS 0.92
     *  - RSS 2.0
     *  - Atom
     *
     * Configuration Options
     *  - array
     *      - url: (string)
     *          - feed url
     *
     *      - httpClient: (string)
     *          - default SimpleXML
     *          - value rayHttp or SimpleXML
     *
     *      - type: ([optional] string
     *          - auto detect
     *          - value rss or rss2 or atom
     *
     *      - widget: ([optional] string)
     *          - feed widget class name for rendering html
     * 
     *      - rayHttp: (array)
     *          - only if httpClient is set to rayHttp
     *          - rayHttp Options if you want to modify rayHttml CURL options
     *          - generally not required.
     *
     *
     * 
     *
     * @version 1.0
     * @author Md. Rayhan Chowdhury
     * @package rayFeedReader
     * @license GPL
     */
    Class RayFeedReader{

        /**
         * Self Instance for Singleton Pattern
         *
         * @var object
         * @access protected
         */
        static private  $__instance;

        /**
         * Instance of Parser Class.
         *
         * @var object Parser Class
         * @access protected
         */
        Protected       $_Parser;

        /**
         * Feed Url
         *
         * @var string feed url
         * @access protected
         */
        protected       $_url;

        /**
         * Runtime Options for reader
         *
         * @var array
         * @access protected
         */
        protected       $_options = array('rayHttp' => array());

        /**
         * Type of feed to be parsed.
         *
         * @var string
         * @access protected
         */
        protected       $_type = "rss";

        /**
         * HttpClient to be used for loading feed content.
         *
         *  - default SimpleXML
         *
         * @var string 'SimpleXML' or 'rayHttp'
         * @access protected
         */
        protected       $_httpClient = "SimpleXML";
        
        /**
         * Widget Class Name
         *
         * @var string
         * @access protected
         */
        protected       $_widget;

        /**
         * Parsed result data
         * 
         * @var array
         * @access protected
         */
        protected       $_content;

        /**
         * Class construct
         *
         * @param array $options
         */
        function __construct($options = array()) {
            $this->setOptions($options);
        }

        /**
         * Get Instance of the class.
         *
         * @param array $options
         * @return object self instance.
         * @access public
         * @static
         */
        static function &getInstance($options = array()) {
            if (is_null(self::$__instance)) {
                self::$__instance = new self($options);
            }
            return self::$__instance;
        }

        /**
         * Set Options for the class
         * 
         * 
         * @param array $options
         * @return object self instance
         * @access public
         */
        function &setOptions($options) {
            if (!empty($options['url'])) {
                $this->_url = $options['url'];
            }

            if (!empty($options['type'])) {
                $this->_type = $options['type'];
            }

            if (!empty($options['httpClient'])) {
                $this->_httpClient = $options['httpClient'];
            }

            if (!empty($options['widget'])) {
                $this->_widget = $options['widget'];
            }

            $this->_options = array_merge($this->_options, $options);

            return $this;
        }

        /**
         * Parse feed contents into an array and return self object
         * 
         * @return object self instance
         * @access public
         */
        function &parse() {
            /**
             * Get/load content
             */
             switch ($this->_httpClient) {
                 case 'SimpleXML':
                     $content = new SimpleXMLElement($this->_url, LIBXML_NOCDATA, true);
                     break;

                 case 'rayHttp':
                     
                     $content = RayHttp::getInstance()->setOptions($this->_options['rayHttp'])->get($this->_url);
                     
                     if (!empty($content)) {
                        $content = new SimpleXMLElement($content, LIBXML_NOCDATA);
                     }
                     break;
             }

             if (empty($content)) {
                 trigger_error("XML format is invalid or broken.", E_USER_ERROR);
             }

            /**
             * Detect Feed Type
             */

             if (empty($this->_type)) {
                    
                    switch ($content->getName()) {
                        case 'rss':
                            foreach ($content->attributes() as $attribute) {
                                if ($attribute->getName() == 'version') {
                                    if ('2.0' == $attribute) {
                                        self::setOptions(array('type' => 'rss2'));
                                    } elseif (in_array($attribute, array('0.92', '0.91'))) {
                                        self::setOptions(array('type' => 'rss'));
                                    }
                                }
                            }
                            break;

                        case 'feed':                            
                            self::setOptions(array('type' => 'atom'));
                            
                            break;
                    }
                 
             }
             
             if (!in_array($this->_type, array('rss', 'rss2', 'atom'))) {

                  trigger_error("Feed type is either invalid or not supported.", E_USER_ERROR);
                  
                  return false;
             }


            /**
             * Parse Feed Content
             */
            switch ($this->_type) {
                case 'rss':
                    $content = $this->parseRss($content);
                    break;

                case 'rss2':
                    $content = $this->parseRss2($content);
                    break;

                case 'atom':
                    $content = $this->parseAtom($content);
                    break;
            }

             if (empty($content)) {                 
                 trigger_error("No content is found.", E_USER_ERROR);
             }

             $this->_content = $content;
             
             return $this;

        }

        /**
         * Get Array of Parsed XML feed data.
         *
         * @return array parsed feed content.
         * @access public
         */
        function getData() {
            return $this->_content;
        }

        /**
         * Return html widget based rendered by widget class
         *
         *
         * @param array $options for html widget class
         * @return string html widget
         * @access public
         */
        function widget($options = array('widget' => 'brief')) {
            if (!empty($this->_widget) && !empty($this->_content)) {
                $Widget = new $this->_widget;
                
                return $Widget->widget($this->_content, $options);
                
             } else {
                 return false;
             }
        }
        
        /**
         * Parse feed xml into an array.
         *
         * @param object $feedXml SimpleXMLElementObject
         * @return array feed content
         * @access public
         */
        function parseRss($feedXml) {
            $data = array();

            $data['title'] = $feedXml->channel->title . '';
            $data['link'] = $feedXml->channel->link . '';
            $data['description'] = $feedXml->channel->description . '';
            $data['parser'] = __CLASS__;
            $data['type'] = 'rss';

            foreach ($feedXml->channel->item as $item) {
                $data['items'][] = array(
                                        'title' =>  $item->title . '',
                                        'link' =>   $item->link . '',
                                        'description' => $item->description . '',
                                    );
            }
            
            return $data;
        }

        
        /**
         * Parse feed xml into an array.
         *
         * @param object $feedXml SimpleXMLElementObject
         * @return array feed content
         * @access public
         */
        function parseRss2($feedXml) {
            $data = array();

            $data['title'] = $feedXml->channel->title . '';
            $data['link'] = $feedXml->channel->link . '';
            $data['description'] = $feedXml->channel->description . '';
            $data['parser'] = __CLASS__;
            $data['type'] = 'rss2';

            $namespaces = $feedXml->getNamespaces(true);
            foreach ($namespaces as $namespace => $namespaceValue) {
                $feedXml->registerXPathNamespace($namespace, $namespaceValue);
            }

            foreach ($feedXml->channel->item as $item) {
                $categories = array();
                foreach ($item->children() as $child) {
                    if ($child->getName() == 'category') {
                        $categories[] = (string) $child;
                    } 
                }

                $author = null;
                if (!empty($namespaces['dc']) && $creator = $item->xpath('dc:creator')) {
                    $author = (string) $creator[0];
                }

                $content = null;
                if (!empty($namespaces['encoded']) && $encoded = $item->xpath('content:encoded')) {
                    $content = (string) $encoded[0];
                }

                $data['items'][] = array(
                                        'title' =>  $item->title . '',
                                        'link' =>   $item->link . '',
                                        'date' =>   date('Y-m-d h:i:s A', strtotime($item->pubDate . '')),
                                        'description' => $item->description . '',
                                        'categories' => $categories,
                                        'author' => array( 'name' => $author),
                                        'content' => $content,
                                        
                                    );
                
            }

            return $data;
        }

        /**
         * Parse feed xml into an array.
         *
         * @param object $feedXml SimpleXMLElementObject
         * @return array feed content
         * @access public
         */
        function parseAtom($feedXml) {
            $data = array();

            $data['title'] = $feedXml->title . '';
            foreach ($feedXml->link as $link) {
                    $data['link'] = $link['href'] . '';
                break;
            }

            $data['description'] = $feedXml->subtitle . '';
            $data['parser'] = __CLASS__;
            $data['type'] = 'atom';

            foreach ($feedXml->entry as $item) {
                foreach ($item->link as $link) {
                    $itemLink = $link['href'] . '';
                    break;
                }

                $categories = array();
                foreach ($item->category as $category) {
                    $categories[] = $category['term'] . '';
                }

                $data['items'][] = array(
                                        'title' =>  $item->title . '',
                                        'link' =>   $itemLink . '',
                                        'date' =>   date('Y-m-d h:i:s A', strtotime($item->published . '')),
                                        'description' => $item->summary . '',
                                        'content' => $item->content . '',
                                        'categories' => $categories,
                                        'author' => array('name' => $item->author->name . '', 'url' => $item->author->uri . ''),
                                        'extra' => array('contentType' => $item->content['type'] . '', 'descriptionType' => $item->summary['type'] . '')
                                    );
            }

            return $data;
        }

    }
?>
Return current item: Ray Feed Reader