[geeklog-cvs] geeklog-1.3/system/classes/syndication atom.feed.class.php,NONE,1.1 feedparserbase.class.php,NONE,1.1 parserfactory.class.php,NONE,1.1 rdf.feed.class.php,NONE,1.1 rss.feed.class.php,NONE,1.1

dhaun at iowaoutdoors.org dhaun at iowaoutdoors.org
Sun Jan 23 06:07:22 EST 2005


Update of /var/cvs/geeklog-1.3/system/classes/syndication
In directory www:/tmp/cvs-serv31343/system/classes/syndication

Added Files:
	atom.feed.class.php feedparserbase.class.php 
	parserfactory.class.php rdf.feed.class.php rss.feed.class.php 
Log Message:
Incorporated new framework for reading and writing feeds (RSS, RDF, Atom), provided by Michael Jervis.


--- NEW FILE: rss.feed.class.php ---
<?php
  /****************************************************************************/
  /* rss.feed.class.php                                                       */
  /*                                                                          */
  /****************************************************************************/
  /* Copyright (c) 2004 Michael Jervis (mike at fuckingbrit.com)                 */
  /*                                                                          */
  /* This software is provided 'as-is', without any express or implied        */
  /* warranty. In no event will the authors be held liable for any damages    */
  /* arising from the use of this software.                                   */
  /*                                                                          */
  /* Permission is granted to anyone to use this software for any purpose,    */
  /* including commercial applications, and to alter it and redistribute it   */
  /* freely, subject to the following restrictions:                           */
  /*                                                                          */
  /*  1. The origin of this software must not be misrepresented; you must not */
  /*     claim that you wrote the original software. If you use this software */
  /*     in a product, an acknowledgment in the product documentation would be*/
  /*     appreciated but is not required.                                     */
  /*                                                                          */
  /*  2. Altered source versions must be plainly marked as such, and must not */
  /*     be misrepresented as being the original software.                    */
  /*                                                                          */
  /*  3. This notice may not be removed or altered from any source            */
  /*     distribution.                                                        */
  /****************************************************************************/

  /**
    * Provides feed handlers for RSS 0.9x and RSS 2.0
    *
    * This library file provides multiple class definitions for dealing with
    * variants of the RSS syndication format. We will <b>not</b> handle RSS 1.0
    * however, that is RDF and handled in a seperate case. This is purely for
    * the original RSS and the 2.0 that was created to deal with the fact
    * that RDF was overkill for the original purpose of RSS.
    *
    * @author Michael Jervis (mike at fuckingbrit.com)
    * @version 1.0
    */

  /**
   * rss0x provides reading and writing of RSS 0.91 format syndication feeds.
   *
   * @author Michael Jervis (mike at fuckingbrit.com)
   * @copyright Michael Jervis 2004
   * @abstract
   */
  class RSS0x extends FeedParserBase
  {
    /**
      * @access private
      * @var boolean
      */
    var $_inItem;

    /**
      * @access private
      * @var array
      */
    var $_currentItem;

    function RSS0x()
    {
      $this->FeedParserBase();
      $this->_inItem = false;
    }

    /**
      * Format an article into an RSS 0.91 <item> tag.
      *
      * Takes an associative article array and turns it into an XML definition
      * of an article. Uses merely title, link and summary.
      *
      * @param array $article Associative array describing an article.
      */
    function _formatArticle( $article )
    {
      $xml = "<item>\n";
      $xml .= '<title>'.$this->_safeXML( $article['title'] )."</title>\n";
      $xml .= '<link>'.$this->_safeXML( $article['link'] )."</link>\n";
      if( array_key_exists( 'summary', $article ) )
      {
        if( strlen( $article['summary'] ) > 0 )
        {
          $xml .= '<description>'.$this->_safeXML( $article['summary'] )."</description>\n";
        }
      }
      $xml .= "</item>\n";
      return $xml;
    }

    /**
      * Return the formatted start of a feed.
      *
      * This will start the xml and create header information about the feed
      * itself.
      */
    function _feedHeader()
    {
      $xml = "<?xml version=\"1.0\" encoding=\"{$this->encoding}\"?>\n\n";
      $xml .= "<rss version=\"0.91\">\n<channel>\n";
      $xml .= "<title>".$this->_safeXML( $this->title )."</title>\n";
      $xml .= "<link>".$this->_safeXML( $this->sitelink )."</link>\n";
      if( strlen( $this->description ) > 0 )
      {
        $xml .= "<description>".$this->_safeXML( $this->description )."</description>\n";
      }
      $xml .= "<lang>{$this->lang}</lang>\n";
      return $xml;
    }

    /**
      * Return the formatted end of a feed.
      *
      * just closes things off nicely.
      */
    function _feedFooter()
    {
      $xml = "</channel>\n</rss>\n";
      return $xml;
    }

    /**
      * Handle the begining of an XML element
      *
      * This is called from the parserfactory once the type of data has been
      * determined. Standard XML_PARSER element handler.
      *
      * @author Michael Jervis (mike at fuckingbrit.com)
      * @copyright Michael Jervis 2004
      */
    function startElement($parser, $name, $attributes)
    {
      if( $name == 'ITEM' )
      {
        $this->_inItem = true;
        $this->_currentItem = array();
      }
      $this->_currentTag = $name;
    }

    /**
      * Handle the close of an XML element
      *
      * Called by the parserfactory during parsing.
      */
    function endElement($parser, $name)
    {
      if( $name == 'ITEM' )
      {
        $this->_inItem = false;
        $this->articles[] = $this->_currentItem;
      }
      $this->_currentTag = '';
    }

    /**
      * Handles character data.
      *
      * Called by the parserfactory during parsing.
      */
    function charData($parser, $data)
    {
      if( $this->_inItem )
      {
        if( $this->_currentTag == 'TITLE' )
        {
          if( empty( $this->_currentItem['title'] ) )
          {
            $this->_currentItem['title'] = $data;
          } else {
            $this->_currentItem['title'] .= $data;
          }
        } else if( $this->_currentTag == 'LINK' ) {
          if( empty( $this->_currentItem['link'] ) )
          {
            $this->_currentItem['link'] = $data;
          } else {
            $this->_currentItem['link'] .= $data;
          }
        } else if( $this->_currentTag == 'DESCRIPTION' ) {
          if( empty( $this->_currentItem['summary'] ) )
          {
            $this->_currentItem['summary'] = $data;
          } else {
            $this->_currentItem['summary'] .= $data;
          }
        }
      } else {
        if( $this->_currentTag == 'TITLE' )
        {
          $this->title .= $data;
        } else if( $this->_currentTag == 'LINK' ) {
          $this->sitelink .= $data;
        } else if( $this->_currentTag == 'DESCRIPTION' ) {
          $this->description .= $data;
        }
      }
    }
  }


  /**
   * rss20 provides reading and writing of RSS 2.0 format syndication feeds.
   *
   * @author Michael Jervis (mike at fuckingbrit.com)
   * @copyright Michael Jervis 2004
   * @abstract
   */
  class RSS20 extends FeedParserBase
  {
    /**
      * @access private
      * @var boolean
      */
    var $_inItem;

    /**
      * @access private
      * @var array
      */
    var $_currentItem;

    /**
      * Date of feed, for reading only
      */
    var $date;

    /**
      * is the guid element a permalink?
      */
    var $_permaLink;

    function RSS20()
    {
      $this->FeedParserBase();
      $this->_inItem = false;
    }

    /**
      * Format an article into an RSS 2.0 <item> tag.
      *
      * Takes an associative article array and turns it into an XML definition
      * of an article. Uses merely title, link and summary.
      *
      * @param array $article Associative array describing an article.
      */
    function _formatArticle( $article )
    {
      $xml = "<item>\n";
      $xml .= '<title>'.$this->_safeXML( $article['title'] )."</title>\n";
      $xml .= '<link>'.$this->_safeXML( $article['link'] )."</link>\n";
      $xml .= '<guid isPermaLink="true">'.$this->_safeXML( $article['link'] )."</guid>\n";
      $xml .= '<pubDate>'.strftime( "%a, %d %b %Y %T %Z", $article['date'] )."</pubDate>\n";
      if( array_key_exists( 'commenturl', $article ) )
      {
        $xml .= '<comments>'.$this->_safeXML( $article['commenturl'] )."</comments>\n";
      }
      if( array_key_exists( 'summary', $article ) )
      {
        if( strlen( $article['summary'] ) > 0 )
        {
          $xml .= '<description>'.$this->_safeXML( $article['summary'] )."</description>\n";
        }
      }
      $xml .= "</item>\n";
      return $xml;
    }

    /**
      * Return the formatted start of a feed.
      *
      * This will start the xml and create header information about the feed
      * itself.
      */
    function _feedHeader()
    {
      $xml = "<?xml version=\"1.0\" encoding=\"{$this->encoding}\"?>\n\n";
      $xml .= "<rss version=\"2.0\">\n<channel>\n";
      $xml .= "<title>".$this->_safeXML( $this->title )."</title>\n";
      $xml .= "<link>".$this->_safeXML( $this->sitelink )."</link>\n";
      if( strlen( $this->description ) > 0 )
      {
        $xml .= "<description>".$this->_safeXML( $this->description )."</description>\n";
      }
      if( strlen($this->sitecontact) > 0 )
      {
        $xml .= '<managingEditor>'.$this->_safeXML( $this->sitecontact )."</managingEditor>\n";
        $xml .= '<webMaster>'.$this->_safeXML( $this->sitecontact )."</webMaster>\n";
      }
      if( strlen($this->copyright) > 0 )
      {
        $xml .= '<copyright>'.$this->_safeXML( $this->copyright )."</copyright>\n";
      }
      if( strlen($this->system) > 0 )
      {
        $xml .= '<generator>'.$this->_safeXML( $this->system )."</generator>\n";
      }
      $xml .= '<pubDate>'.strftime( "%a, %d %b %Y %T %Z" )."</pubDate>\n";
      $xml .= "<language>{$this->lang}</language>\n";

      return $xml;
    }

    /**
      * Return the formatted end of a feed.
      *
      * just closes things off nicely.
      */
    function _feedFooter()
    {
      $xml = "</channel>\n</rss>\n";
      return $xml;
    }

    /**
      * Handle the begining of an XML element
      *
      * This is called from the parserfactory once the type of data has been
      * determined. Standard XML_PARSER element handler.
      *
      * @author Michael Jervis (mike at fuckingbrit.com)
      * @copyright Michael Jervis 2004
      */
    function startElement($parser, $name, $attributes)
    {
      if( $name == 'ITEM' )
      {
        $this->_inItem = true;
        $this->_currentItem = array();
        $this->_permaLink = false;
      } else if( ($name == 'GUID') && array_key_exists('ISPERMALINK', $attributes) ) {
        if( $attributes['ISPERMALINK'] == 'true' )
        {
          $this->_permaLink = true;
        } else {
          $this->_permaLink = false;
        }
      } else {
        $this->_permaLink = false;
      }
      $this->_currentTag = $name;
    }

    /**
      * Handle the close of an XML element
      *
      * Called by the parserfactory during parsing.
      */
    function endElement($parser, $name)
    {
      if( $name == 'ITEM' )
      {
        $this->_inItem = false;
        $this->articles[] = $this->_currentItem;
      }
      $this->_currentTag = '';
    }

    /**
      * Handles character data.
      *
      * Called by the parserfactory during parsing.
      */
    function charData($parser, $data)
    {
      if( $this->_inItem )
      {
        if( $this->_currentTag == 'TITLE' )
        {
          $this->_currentItem['title'] = $data;
        } else if( $this->_currentTag == 'LINK' ) {
          if( $this->_currentItem['link'] == '' )
          {
            $this->_currentItem['link'] = $data;
          }
        } else if( $this->_currentTag == 'DESCRIPTION' ) {
          $this->_currentItem['summary'] = $data;
        } else if( $this->_currentTag == 'PUBDATE' ) {
          $this->_currentItem['date'] = $data;
        } else if( ($this->_currentTag == 'GUID') && $this->_permaLink) {
          /* if we have a guid that is ALSO a permalink, override link with it */
          $this->_currentItem['link'] = $data;
        }
      } else {
        if( $this->_currentTag == 'TITLE' )
        {
          $this->title .= $data;
        } else if( $this->_currentTag == 'LINK' ) {
          $this->sitelink .= $data;
        } else if( $this->_currentTag == 'DESCRIPTION' ) {
          $this->description .= $data;
        } else if( $this->_currentTag == 'MANAGINGEDITOR' ) {
          $this->sitecontact .= $data;
        } else if( $this->_currentTag == 'COPYRIGHT' ) {
          $this->copyright .= $data;
        } else if( $this->_currentTag == 'PUBDATE' ) {
          $this->date .= $data;
        }
      }
    }
  }
?>
--- NEW FILE: atom.feed.class.php ---
<?php
  /****************************************************************************/
  /* atom.feed.class.php                                                      */
  /*                                                                          */
  /****************************************************************************/
  /* Copyright (c) 2004 Michael Jervis (mike at fuckingbrit.com)                 */
  /*                                                                          */
  /* This software is provided 'as-is', without any express or implied        */
  /* warranty. In no event will the authors be held liable for any damages    */
  /* arising from the use of this software.                                   */
  /*                                                                          */
  /* Permission is granted to anyone to use this software for any purpose,    */
  /* including commercial applications, and to alter it and redistribute it   */
  /* freely, subject to the following restrictions:                           */
  /*                                                                          */
  /*  1. The origin of this software must not be misrepresented; you must not */
  /*     claim that you wrote the original software. If you use this software */
  /*     in a product, an acknowledgment in the product documentation would be*/
  /*     appreciated but is not required.                                     */
  /*                                                                          */
  /*  2. Altered source versions must be plainly marked as such, and must not */
  /*     be misrepresented as being the original software.                    */
  /*                                                                          */
  /*  3. This notice may not be removed or altered from any source            */
  /*     distribution.                                                        */
  /****************************************************************************/

  /**
    * Provides feed handlers for Atom 0.3
    *
    * @author Michael Jervis (mike at fuckingbrit.com)
    * @version 1.0
    */

  /**
   * atom03 provides reading and writing of Atom 0.3 format syndication feeds.
   *
   * @author Michael Jervis (mike at fuckingbrit.com)
   * @copyright Michael Jervis 2004
   * @abstract
   */
  class Atom03 extends FeedParserBase
  {
    /**
      * @access private
      * @var boolean
      */
    var $_inItem;

    /**
      * @access private
      * @var array
      */
    var $_currentItem;

    function Atom03()
    {
      $this->FeedParserBase();
      $this->_inItem = false;
    }

    /**
      * Format an article into an Atom 0.3 <entry> tag.
      *
      * Takes an associative article array and turns it into an XML definition
      * of an article. Uses merely title, link and summary.
      *
      * @param array $article Associative array describing an article.
      */
    function _formatArticle( $article )
    {
      $xml = "<entry>\n";
      $xml .= '<title mode="escaped">'.$this->_safeXML( $article['title'] )."</title>\n";
      $xml .= '<link rel="alternative" type="text/html" href="'.$this->_safeXML( $article['link'] )."\">\n";
      $xml .= '<id>'.htmlspecialchars( $entry['link'] )."</id>\n";
      $xml .= '<issued>'.strftime( "%a, %d %b %Y %T %Z", $article['date'] )."</issued>\n";
      $xml .= '<modified>'.strftime( "%a, %d %b %Y %T %Z", $article['date'] )."</modified>\n";
      if( array_key_exists( 'author', $article ) )
      {
        $xml .= "<author>\n<name>{$article['author']}</name>\n</author>\n";
      }
      if( array_key_exists( 'summary', $article ) )
      {
        if( strlen( $article['summary'] ) > 0 )
        {
          $xml .= '<content type="text/html" mode="escaped">'
                          . $this->_safeXML ($article['text'])
                          . "</content>\n";
        }
      }
      $xml .= "</entry>\n";
      return $xml;
    }

    /**
      * Return the formatted start of a feed.
      *
      * This will start the xml and create header information about the feed
      * itself.
      */
    function _feedHeader()
    {
      $xml = "<?xml version=\"1.0\" encoding=\"{$this->encoding}\"?>\n\n";
      $xml .= "<feed version=\"0.3\">\n";
      $xml .= "<title mode=\"escaped\">".$this->_safeXML( $this->title )."</title>\n";
      $xml .= '<tagline mode=\"escaped\">'.$this->_safeXML( $this->description )."</tagline>\n";
      $xml .= '<link rel="alternative" type="text/html" href="'.$this->_safeXML( $this->sitelink )."\"/>\n";
      return $xml;
    }

    /**
      * Return the formatted end of a feed.
      *
      * just closes things off nicely.
      */
    function _feedFooter()
    {
      $xml = "</feed>\n";
      return $xml;
    }

    /**
      * Handle the begining of an XML element
      *
      * This is called from the parserfactory once the type of data has been
      * determined. Standard XML_PARSER element handler.
      *
      * @author Michael Jervis (mike at fuckingbrit.com)
      * @copyright Michael Jervis 2004
      */
    function startElement($parser, $name, $attributes)
    {
      if( $name == 'ENTRY' )
      {
        $this->_inItem = true;
        $this->_currentItem = array();
      } else if( $this->_inItem ) {
        if( $name == 'LINK' )
        {
          $this->_currentItem['link'] = $attributes['HREF'];
        }
      } else {
        if( $name == 'LINK' )
        {
          $this->sitelink = $attributes['HREF'];
        }
      }
      $this->_currentTag = $name;
    }

    /**
      * Handle the close of an XML element
      *
      * Called by the parserfactory during parsing.
      */
    function endElement($parser, $name)
    {
      if( $name == 'ENTRY' )
      {
        $this->_inItem = false;
        $this->articles[] = $this->_currentItem;
      }
      $this->_currentTag = '';
    }

    /**
      * Handles character data.
      *
      * Called by the parserfactory during parsing.
      */
    function charData($parser, $data)
    {
      if( $this->_inItem )
      {
        if( $this->_currentTag == 'TITLE' )
        {
          if( empty( $this->_currentItem['title'] ) )
          {
            $this->_currentItem['title'] = $data;
          } else {
            $this->_currentItem['title'] .= $data;
          }
        } else if( $this->_currentTag == 'CONTENT' ) {
          if( empty( $this->_currentItem['summary'] ) )
          {
            $this->_currentItem['summary'] = $data;
          } else {
            $this->_currentItem['summary'] .= $data;
          }
        } else if( $this->_currentTag == 'MODIFIED' ) {
          $this->_currentItem['date'] = $data;
        } else if( $this->_currentTag == 'ISSUED' ) {
          if( empty( $this->currentItem['date'] ) )
          {
            $this->currentITem['date'] = $data;
          }
        }
      } else {
        if( $this->_currentTag == 'TITLE' )
        {
          $this->title .= $data;
        } else if( $this->_currentTag == 'TAGLINE' ) {
          $this->description .= $data;
        }
      }
    }
  }
--- NEW FILE: parserfactory.class.php ---
<?php
  /****************************************************************************/
  /* feedparserfactory.class.php                                              */
  /*                                                                          */
  /****************************************************************************/
  /* Copyright (c) 2004 Michael Jervis (mike at fuckingbrit.com)                 */
  /*                                                                          */
  /* This software is provided 'as-is', without any express or implied        */
  /* warranty. In no event will the authors be held liable for any damages    */
  /* arising from the use of this software.                                   */
  /*                                                                          */
  /* Permission is granted to anyone to use this software for any purpose,    */
  /* including commercial applications, and to alter it and redistribute it   */
  /* freely, subject to the following restrictions:                           */
  /*                                                                          */
  /*  1. The origin of this software must not be misrepresented; you must not */
  /*     claim that you wrote the original software. If you use this software */
  /*     in a product, an acknowledgment in the product documentation would be*/
  /*     appreciated but is not required.                                     */
  /*                                                                          */
  /*  2. Altered source versions must be plainly marked as such, and must not */
  /*     be misrepresented as being the original software.                    */
  /*                                                                          */
  /*  3. This notice may not be removed or altered from any source            */
  /*     distribution.                                                        */
  /****************************************************************************/

  /**
   * FeedParserFactory provides generic access to syndication feed formats.
   *
   * <p>This library provides abstraction of feed formats. It provides a factory
   * pattern interface to constructing feed handlers to parse incoming
   * syndication files, and write outgoing syndication files. The interface is
   * not tied to any system implementation, however, I plan to provide interface
   * to geeklog.</p>
   *
   * @author Michael Jervis (mike at Fuckingbrit.com)
   * @copyright Michael Jervis 2004
   * @see FeedParserBase
   */
  class FeedParserFactory
  {
    var $readerName;
    var $reader;

    /**
      * Constructor, loads feedparser classes into memory.
      *
      * This takes a path on which the supporting feed classes exist, and then
      * tries to find all *.feed.class.php and brings them into scope.
      *
      * @param string $path path to include files from.
      */
    function FeedParserFactory( $path='' )
    {
      if( $path != '' )
      {
        if( is_dir( $path ) )
        {
          $folder = opendir( $path );
          while( ( $filename = @readdir( $folder ) ) !== false )
          {
            if( preg_match( '/(.*)\.feed\.class\.php$/i', $filename ) )
            {
              require_once( $path.'/'.$filename );
            }
          }
        }
      }
    }

    /**
      * Method to get a feed handler class.
      *
      * This function takes a url, fetches it, parses it, and thus figures out
      * what type of feed parser to return, with the contents all parsed for your
      * viewing pleasure.
      *
      * @access public
      * @param string $url The url to a feed type to syndicate.
      */
    function reader( $url, $targetformat='' )
    {
      if( $fp = $this->_getFeed( $url ) )
      {
        return $this->_findFeed( $fp );
      } else {
        return false;
      }
    }

    /**
      * Method to get a feed handler class.
      *
      * this function assumes you know what you want, and gets you a blank feed
      * handler to write that data.
      *
      * @access public
      * @param string $feedtype the type of feed to get
      * @param float $version the version
      */
    function writer( $feedtype, $version=2.0 )
    {
      $feedtype = strtolower($feedtype);
      switch ($feedtype)
      {
        case 'rss':
          if( $version == '' )
          {
            return new RSS0x();
          } else {
            if( $version < 1.0 )
            {
              return new RSS0x();
            } else if( $version >= 2.0 ) {
              return new RSS20();
            } else {
              return new RSS0x();
            }
          }
          break;
        case 'rdf':
          return new RDF();
          break;
        case 'atom':
          return new Atom03();
          break;
        default:
          return false;
          break;
      }
    }

    /**
      * Provides an array of feed types understood.
      *
      * Provides an array of feed types understood. Yeah it's manual, but, the
      * feed reader has to be edited to support new inbounds anyway.
      *
      * @access public
      */
    function getFeedTypes()
    {
      $types = array();
      $types[] = array('name'=>'RSS','version'=>'0.9x');
      $types[] = array('name'=>'RSS','version'=>'2.0');
      $types[] = array('name'=>'RDF','version'=>'1.0');
      $types[] = array('name'=>'Atom','version'=>'0.3');
      return $types;
    }

    /**
      * Opens a url in a file pointer
      *
      * @access private
      * @param string $url The URL to open.
      */
    function _getFeed( $url )
    {
      if( $fp = @fopen( $url, 'r' ) )
      {
        return $fp;
      } else {
        return false;
      }
    }

    /**
      * Find out what format a feed is in.
      *
      * @access private
      */
    function _findFeed( $fp, $format='' )
    {
      $xml_parser = xml_parser_create();
      xml_parser_set_option( $xml_parser, XML_OPTION_CASE_FOLDING, true );
      if( $format != '' )
      {
        @xml_parser_set_option( $xml_parser, XML_OPTION_TARGET_ENCODING,
                                $format );
      }
      xml_set_element_handler( $xml_parser, array(&$this,'_startElement'), array(&$this, '_endElement') );
      xml_set_character_data_handler( $xml_parser, array(&$this,'_charData') );

      while( $data = fread( $fp, 4096 ) )
      {
        if( !xml_parse( $xml_parser, $data, feof($fp) ) )
        {
          fclose($fp);
          xml_parser_free( $xml_parser );
          return false;
        }
      }
      fclose( $fp );
      xml_parser_free( $xml_parser );

      if( $this->reader != false )
      {
        return $this->reader;
      } else {
        return false;
      }
    }

    function _startElement( $parser, $name, $attributes )
    {
      if( !$this->readerName )
      {
        /* Check for atom */
        if( $name == 'FEED' )
        {
          $this->readerName = 'Atom03';
        } elseif ( $name == 'RSS' ) {
          if( array_key_exists('VERSION', $attributes) )
          {
            $version = $attributes['VERSION'];
          } else {
            $version = 0.91;
          }
          if( $version < 1 )
          {
            $this->readerName = 'RSS0x';
          } else {
            $this->readerName = 'RSS20';
          }
        } elseif ( $name = 'RDF:RDF' ) {
          $this->readerName = 'RDF';
        }
        if( $this->readerName )
        {
          $this->reader = new $this->readerName;
          //echo( "Made a new {$this->readerName} called {$this->reader} it's a ".get_class($this->reader)." I'm a ".get_class($this) );
        }
      }

      if( $this->reader )
      {
        $this->reader->startElement( $parser, $name, $attributes );
      }
    }

    function _endElement( $parser, $name )
    {
      if( $this->reader )
      {
        $this->reader->endElement( $parser, $name );
      }
    }

    function _charData( $parser, $data )
    {
      if( $this->reader )
      {
        $this->reader->charData( $parser, $data );
      }
    }
  }
?>
--- NEW FILE: rdf.feed.class.php ---
<?php
  /****************************************************************************/
  /* rdf.feed.class.php                                                       */
  /*                                                                          */
  /****************************************************************************/
  /* Copyright (c) 2004 Michael Jervis (mike at fuckingbrit.com)                 */
  /*                                                                          */
  /* This software is provided 'as-is', without any express or implied        */
  /* warranty. In no event will the authors be held liable for any damages    */
  /* arising from the use of this software.                                   */
  /*                                                                          */
  /* Permission is granted to anyone to use this software for any purpose,    */
  /* including commercial applications, and to alter it and redistribute it   */
  /* freely, subject to the following restrictions:                           */
  /*                                                                          */
  /*  1. The origin of this software must not be misrepresented; you must not */
  /*     claim that you wrote the original software. If you use this software */
  /*     in a product, an acknowledgment in the product documentation would be*/
  /*     appreciated but is not required.                                     */
  /*                                                                          */
  /*  2. Altered source versions must be plainly marked as such, and must not */
  /*     be misrepresented as being the original software.                    */
  /*                                                                          */
  /*  3. This notice may not be removed or altered from any source            */
  /*     distribution.                                                        */
  /****************************************************************************/

  /**
    * Provides feed handlers for RDF 1.0
    *
    * @author Michael Jervis (mike at fuckingbrit.com)
    * @version 1.0
    */

  /**
   * RDF provides reading and writing of RDF 1.0 format syndication feeds.
   *
   * @author Michael Jervis (mike at fuckingbrit.com)
   * @copyright Michael Jervis 2004
   * @abstract
   */
  class RDF extends FeedParserBase
  {
    /**
      * @access private
      * @var boolean
      */
    var $_inItem;

    /**
      * @access private
      * @var array
      */
    var $_currentItem;

    function RDF()
    {
      $this->FeedParserBase();
      $this->_inItem = false;
    }

    /**
      * Format an article into an Atom 0.3 <entry> tag.
      *
      * Takes an associative article array and turns it into an XML definition
      * of an article. Uses merely title, link and summary.
      *
      * @param array $article Associative array describing an article.
      */
    function _formatArticle( $article )
    {
      $xml = "<item rdf:about=\"{$article['link']}\">\n";
      $xml .= '<title>'.$this->_safeXML( $article['title'] )."</title>\n";
      $xml .= '<link>'.$this->_safeXML( $article['link'] )."</link>\n";
      if( array_key_exists( 'author', $article ) )
      {
        $xml .= '<dc:creator>'.$article['author']."</dc:creator>\n";
      }
      if( array_key_exists( 'summary', $article ) )
      {
        if( strlen( $article['summary'] ) > 0 )
        {
          $xml .= '<content:encoded>'
                          . $this->_safeXML ($article['text'])
                          . "</content:encoded>\n";
        }
      }
      $xml .= "</item>\n";
      return $xml;
    }

    /**
      * Return the formatted start of a feed.
      *
      * This will start the xml and create header information about the feed
      * itself.
      */
    function _feedHeader()
    {
      $xml = "<?xml version=\"1.0\" encoding=\"{$this->encoding}\"?>\n\n";
      $xml .= "<rdf:RDF>\n<channel>\n";
      $xml .= "<title>".$this->_safeXML( $this->title )."</title>\n";
      $xml .= '<link>'.$this->_safeXML( $this->sitelink )."</link>\n";
      $xml .= '<description>'.$this->_safeXML( $this->description )."</description>\n";
      $xml .= '<dc:language>'.$this->lang."</dc:language>\n";
      if( strlen($this->sitecontact) > 0 )
      {
        $xml .= '<dc:creator>'.$this->sitecontact."</dc:creator>\n";
      }
      $xml .= "<items>\n<rdf:Seq/>\n</items></channel>\n";

      return $xml;
    }

    /**
      * Return the formatted end of a feed.
      *
      * just closes things off nicely.
      */
    function _feedFooter()
    {
      $xml = "</rdf:RDF>\n";
      return $xml;
    }

    /**
      * Handle the begining of an XML element
      *
      * This is called from the parserfactory once the type of data has been
      * determined. Standard XML_PARSER element handler.
      *
      * @author Michael Jervis (mike at fuckingbrit.com)
      * @copyright Michael Jervis 2004
      */
    function startElement($parser, $name, $attributes)
    {
      if( $name == 'ITEM' )
      {
        $this->_inItem = true;
        $this->_currentItem = array();
      }
      $this->_currentTag = $name;
    }

    /**
      * Handle the close of an XML element
      *
      * Called by the parserfactory during parsing.
      */
    function endElement($parser, $name)
    {
      if( $name == 'ITEM' )
      {
        $this->_inItem = false;
        $this->articles[] = $this->_currentItem;
      }
      $this->_currentTag = '';
    }

    /**
      * Handles character data.
      *
      * Called by the parserfactory during parsing.
      */
    function charData($parser, $data)
    {
      if( $this->_inItem )
      {
        if( $this->_currentTag == 'TITLE' )
        {
          if( empty( $this->_currentItem['title'] ) )
          {
            $this->_currentItem['title'] = $data;
          } else {
            $this->_currentItem['title'] .= $data;
          }
        } else if( $this->_currentTag == 'LINK' ) {
          if( empty( $this->_currentItem['link'] ) )
          {
            $this->_currentItem['link'] = $data;
          } else {
            $this->_currentItem['link'] .= $data;
          }
        } else if( $this->_currentTag == 'CONTENT:ENCODED' ) {
          if( empty( $this->_currentItem['summary'] ) )
          {
            $this->_currentItem['summary'] = $data;
          } else {
            $this->_currentItem['summary'] .= $data;
          }
        }
      } else {
        if( $this->_currentTag == 'TITLE' )
        {
          $this->title .= $data;
        } else if( $this->_currentTag == 'LINK' ) {
          $this->sitelink .= $data;
        } else if( $this->_currentTag == 'DESCRIPTION' ) {
          $this->description .= $data;
        }
      }
    }
  }
--- NEW FILE: feedparserbase.class.php ---
<?php
  /****************************************************************************/
  /* FeedParserBase.class.php                                                 */
  /*                                                                          */
  /****************************************************************************/
  /* Copyright (c) 2004 Michael Jervis (mike at fuckingbrit.com)                 */
  /*                                                                          */
  /* This software is provided 'as-is', without any express or implied        */
  /* warranty. In no event will the authors be held liable for any damages    */
  /* arising from the use of this software.                                   */
  /*                                                                          */
  /* Permission is granted to anyone to use this software for any purpose,    */
  /* including commercial applications, and to alter it and redistribute it   */
  /* freely, subject to the following restrictions:                           */
  /*                                                                          */
  /*  1. The origin of this software must not be misrepresented; you must not */
  /*     claim that you wrote the original software. If you use this software */
  /*     in a product, an acknowledgment in the product documentation would be*/
  /*     appreciated but is not required.                                     */
  /*                                                                          */
  /*  2. Altered source versions must be plainly marked as such, and must not */
  /*     be misrepresented as being the original software.                    */
  /*                                                                          */
  /*  3. This notice may not be removed or altered from any source            */
  /*     distribution.                                                        */
  /****************************************************************************/

  /**
   * FeedParserBase provides an abstract ancestor class for feed parsers.
   *
   * @author Michael Jervis (mike at fuckingbrit.com)
   * @copyright Michael Jervis 2004
   * @abstract
   */
  class FeedParserBase
  {
    /**
      * An array of items.
      *
      * This holds all the news from the source. This should be an array of
      * associative arrays. Each item will have:
      * title - The title
      * URI - Link to the full story
      * date - The date of the article
      * Optional (pre-defined) items are:
      * summary - Short version of article
      * text - full version
      * author - Who wrote the article
      */
    var $articles;

    /**
      * Encoding tag for the XML declaration
      */
    var $encoding;

    /**
      * Language for the feed
      */
    var $lang;

    /**
      * Title for the feed
      */
    var $title;

    /**
      * The description of the feed
      */
    var $description;

    /**
      * The URL of the feed
      */
    var $url;

    /**
      * URL of the site
      */
    var $sitelink;

    /**
      * Site contact
      */
    var $sitecontact;

    /**
      * copyright tag:
      */
    var $copyright;

    /**
      * system powering the feed
      */
    var $system;

    /**
      * Stuff for parsing XML
      */
    var $_currentTag;

    function FeedParserBase()
    {
      $this->encoding = 'iso-8859-1';
      $title = 'Killer Feed System Feed';
      $this->lang = 'en-gb';
      $currentTag = '';
      $articles = array();
    }

    /**
      * Create a file for the stream
      *
      * Writes the $items content to the file supplied in the format we have
      * specified. Uses the (abstract) function formatArticle to return XML
      * for an article.
      *
      * @param string $fileName The fully qualified path to the file to create.
      * @param integer $limit (optional) max number of items to write.
      */
    function createFeed( $fileName, $limit='' )
    {
      /* If we have no items, return false */
      if( count( $this->articles ) == 0 )
      {
        return false;
      } else {
        /* Start the XML Feed formating */
        $xml = $this->_feedHeader();

        /* Start with a limit of the size of the array, then, if we have a
         * specific max length use that unless it's bigger than our count */
        $count = count( $this->articles );
        if( $limit )
        {
          if( $limit < $count )
          {
            $count = $limit;
          }
        }

        /* Put the first $count items into the xml, using formatArticle */
        for( $i = 0; $i < $count; $i++ )
        {
          $xml .= $this->_formatArticle( $this->articles[$i] );
        }

        /* Close off the feed */
        $xml .= $this->_feedFooter();

        /* And write it to file */
        return $this->_writeFile( $fileName, $xml );
      }
    }

    function _writeFile( $fileName, $data )
    {
      if( $fp = @fopen( $fileName, 'w' ) )
      {
        fputs( $fp, $data );
        fclose( $fp );
        return true;
      } else {
        return false;
      }
    }

    /**
      * Format an article into feed specific XML.
      *
      * Takes an associative article array and turns it into an XML definition
      * of an article.
      * @param array $article ASsociative array describing an article.
      */
    function _formatArticle( $article )
    {
      $xml = "<article>\n";
      while( list($key, $value) = each( $article ) )
      {
        $value = $this->safeXML( $value );
        $xml .= "<$key>$value</$key>\n>";
      }
      $xml .= "</article>\n";
      return $xl;
    }

    /**
      * Make sure a string is safe to be chardata in an xml element
      *
      * @param string $string the string to escape.
      */
    function _safeXML( $string )
    {
      return htmlspecialchars($string);
    }

    /**
      * Return the formatted start of a feed.
      *
      * This will start the xml and create header information about the feed
      * itself.
      */
    function _feedHeader()
    {
      $xml = "<?xml version=\"1.0\" encoding=\"{$this->encoding}\"?>\n\n";
      $xml .= "<feed>\n<title>{$this->title}</title>\n";
      return $xml;
    }

    /**
      * Return the formatted end of a feed.
      *
      * just closes things off nicely.
      */
    function _feedFooter()
    {
      $xml = '</feed>';
      return $xml;
    }

    /**
      * Handle the begining of an XML element
      *
      * This is called from the parserfactory once the type of data has been
      * determined. Standard XML_PARSER element handler.
      *
      * @author Michael Jervis (mike at fuckingbrit.com)
      * @copyright Michael Jervis 2004
      */
    function startElement($parser, $name, $attributes)
    {
    }

    /**
      * Handle the close of an XML element
      *
      * Called by the parserfactory during parsing.
      */
    function endElement($parser, $name)
    {
    }

    /**
      * Handles character data.
      *
      * Called by the parserfactory during parsing.
      */
    function charData($parser, $data)
    {
    }
  }
?>



More information about the geeklog-cvs mailing list