plugins/SpecialRSS.php
changeset 0 cdf76b0e1aa1
child 1 327d3c7cd3f3
equal deleted inserted replaced
-1:000000000000 0:cdf76b0e1aa1
       
     1 <?php
       
     2 /*
       
     3 Plugin Name: RSS Backend
       
     4 Plugin URI: http://enano.homelinux.org/Feed_me
       
     5 Description: Provides the page Special:RSS, which is used to generate RSS feeds of site and page content changes.
       
     6 Author: Dan Fuhry
       
     7 Version: 1.0
       
     8 Author URI: http://enano.homelinux.org/
       
     9 */
       
    10 
       
    11 /*
       
    12  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
       
    13  * Version 1.0 release candidate 2
       
    14  * Copyright (C) 2006-2007 Dan Fuhry
       
    15  *
       
    16  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
       
    17  * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
       
    18  *
       
    19  * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
       
    20  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
       
    21  */
       
    22  
       
    23 global $db, $session, $paths, $template, $plugins; // Common objects
       
    24 
       
    25 $plugins->attachHook('base_classes_initted', '
       
    26   $paths->add_page(Array(
       
    27     \'name\'=>\'RSS Feed - Latest changes\',
       
    28     \'urlname\'=>\'RSS\',
       
    29     \'namespace\'=>\'Special\',
       
    30     \'special\'=>0,\'visible\'=>0,\'comments_on\'=>0,\'protected\'=>1,\'delvotes\'=>0,\'delvote_ips\'=>\'\',
       
    31     ));
       
    32   ');
       
    33 
       
    34 $plugins->attachHook('session_started', '__enanoRSSAttachHTMLHeaders();');
       
    35 
       
    36 function __enanoRSSAttachHTMLHeaders()
       
    37 {
       
    38   global $db, $session, $paths, $template, $plugins; // Common objects
       
    39   $template->add_header('<link rel="alternate" title="'.getConfig('site_name').' Changes feed" href="'.makeUrlNS('Special', 'RSS/recent', null, true).'" type="application/rss+xml" />');
       
    40   $template->add_header('<link rel="alternate" title="'.getConfig('site_name').' Comments feed" href="'.makeUrlNS('Special', 'RSS/comments', null, true).'" type="application/rss+xml" />');
       
    41 }
       
    42 
       
    43 define('ENANO_FEEDBURNER_INCLUDED', true);
       
    44 
       
    45 /**
       
    46  * Class for easily generating RSS feeds.
       
    47  * @package Enano
       
    48  * @subpackage Feed Me
       
    49  * @license GNU General Public License <http://www.gnu.org/licenses/gpl.html>
       
    50  */
       
    51  
       
    52 class RSS
       
    53 {
       
    54   
       
    55   /**
       
    56    * List of channels contained in this feed.
       
    57    * @var array
       
    58    */
       
    59   
       
    60   var $channels = Array();
       
    61   
       
    62   /**
       
    63    * The channel that's currently being operated on
       
    64    * @var array
       
    65    */
       
    66   
       
    67   var $this_channel = Array();
       
    68   
       
    69   /**
       
    70    * GUID of the current channel
       
    71    * @var string
       
    72    */
       
    73   
       
    74   var $this_guid = '';
       
    75   
       
    76   /**
       
    77    * List of fully XML-formatted feed entries.
       
    78    * @var array
       
    79    */
       
    80   
       
    81   var $items = Array();
       
    82   
       
    83   /**
       
    84    * Constructor.
       
    85    * @param string Feed title
       
    86    * @param string Feed description
       
    87    * @param string Linkback
       
    88    * @param string Generator
       
    89    * @param string E-mail of webmaster
       
    90    */
       
    91   
       
    92   function __construct($title = false, $desc = false, $link = false, $gen = false, $email = false)
       
    93   {
       
    94     $this->create_channel($title, $desc, $link, $gen, $email);
       
    95   }
       
    96   
       
    97   /**
       
    98    * PHP 4 constructor.
       
    99    */
       
   100   
       
   101   function RSS($title = false, $desc = false, $link = false, $gen = false, $email = false)
       
   102   {
       
   103     $this->__construct($title, $desc, $link, $gen, $email);
       
   104   }
       
   105   
       
   106   /** 
       
   107    * Creates a new channel.
       
   108    */
       
   109   
       
   110   function create_channel($title = false, $desc = false, $link = false, $gen = false, $email = false)
       
   111   {
       
   112     if ( empty($title) )
       
   113       $title = 'Untitled feed';
       
   114     else
       
   115       $title = htmlspecialchars($title);
       
   116     if ( empty($desc) )
       
   117       $desc = 'Test feed';
       
   118     else
       
   119       $desc = htmlspecialchars($desc);
       
   120     if ( empty($link) )
       
   121       $link = 'http' . ( isset($_SERVER['HTTPS']) ? 's' : '' ) . '://'.$_SERVER['HTTP_HOST'] . scriptPath . '/';
       
   122     else
       
   123       $link = htmlspecialchars($link);
       
   124     if ( !empty($gen) )
       
   125       $gen = htmlspecialchars($gen);
       
   126     else
       
   127       $gen = 'Enano CMS ' . enano_version();
       
   128     if ( !empty($email) )
       
   129       $email = htmlspecialchars($email);
       
   130     else
       
   131       $email = getConfig('contact_email');
       
   132     
       
   133     $this->channels = Array();
       
   134     $guid = md5(microtime() . mt_rand());
       
   135     $this->channels[$guid] = Array(
       
   136         'title' => $title,
       
   137         'link' => $link,
       
   138         'gen' => $gen,
       
   139         'email' => $email,
       
   140         'lang' => 'en-us',
       
   141         'items' => Array()
       
   142       );
       
   143     $this->this_channel =& $this->channels[$guid];
       
   144     $this->this_guid = $guid;
       
   145     return $guid;
       
   146   }
       
   147   
       
   148   /**
       
   149    * Selects a specific channel to add items to
       
   150    * @param string The GUID of the channel
       
   151    */
       
   152   
       
   153   function select_channel($guid)
       
   154   {
       
   155     if ( isset($this->channels[$guid]) )
       
   156     {
       
   157       $this->this_channel =& $this->channels[$guid];
       
   158       $this->guid = $guid;
       
   159     }
       
   160   }
       
   161   
       
   162   /**
       
   163    * Adds a news item.
       
   164    * @param string Title of the feed entry
       
   165    * @param string Link to where more information can be found
       
   166    * @param string Short description or content area
       
   167    * @param string Date the item was published. If this is a UNIX timestamp it will be formatted with date().
       
   168    * @param string A Globally-Unique Identifier (GUID) for this item. Doesn't have to be a 128-bit hash - usually it's a link. If one is not provided, one is generated based on the first three parameters.
       
   169    */
       
   170   
       
   171   function add_item($title, $link, $desc, $pubdate, $guid = false)
       
   172   {
       
   173     $title = htmlspecialchars($title);
       
   174     $link = htmlspecialchars($link);
       
   175     $desc = '<![CDATA[ ' . str_replace(']]>', ']]&gt;', $desc) . ']]>';
       
   176     if ( is_int($pubdate) || ( !is_int($pub_date) && preg_match('/^([0-9]+)$/', $pubdate) ) )
       
   177     {
       
   178       $pubdate = date('D, d M Y H:i:s T', intval($pubdate));
       
   179     }
       
   180     if ( !$guid )
       
   181     {
       
   182       $guid = md5 ( $title . $link . $desc . $pubdate );
       
   183       $sec1 = substr($guid, 0, 8);
       
   184       $sec2 = substr($guid, 8, 4);
       
   185       $sec3 = substr($guid, 12, 4);
       
   186       $sec4 = substr($guid, 16, 4);
       
   187       $sec5 = substr($guid, 20, 12);
       
   188       $guid = sprintf('%s-%s-%s-%s-%s', $sec1, $sec2, $sec3, $sec4, $sec5);
       
   189     }
       
   190     $xml = "    <item>
       
   191       <title>$title</title>
       
   192       <link>$link</link>
       
   193       <description>
       
   194         $desc
       
   195       </description>
       
   196       <pubDate>$pubdate</pubDate>
       
   197       <guid>$guid</guid>
       
   198     </item>";
       
   199     $this->this_channel['items'][] = $xml;
       
   200   }
       
   201   
       
   202   /**
       
   203    * Converts everything into the final RSS feed.
       
   204    * @param bool If true, XML headers ("<?xml version="1.0" encoding="utf-8" ?>") are included. Defaults to true.
       
   205    * @return string
       
   206    */
       
   207   
       
   208   function render($headers = true)
       
   209   {
       
   210     $xml = '';
       
   211     if ( $headers )
       
   212       // The weird quotes are because of a jEdit syntax highlighting bug
       
   213       $xml .= "<?xml version=".'"'."1.0".'"'." encoding=".'"'."utf-8".'"'." ?>\n";
       
   214     $xml .= "<rss version=".'"'."2.0".'"'.">\n";
       
   215     foreach ( $this->channels as $channel )
       
   216     {
       
   217       $xml .= "  <channel>
       
   218     <title>{$channel['title']}</title>
       
   219     <link>{$channel['link']}</link>
       
   220     <description>{$channel['desc']}</description>
       
   221     <generator>{$channel['gen']}</generator>
       
   222     <webMaster>{$channel['email']}</webMaster>
       
   223     <language>{$channel['lang']}</language>
       
   224 
       
   225 ";
       
   226       $content = implode("\n", $channel['items']) . "\n";
       
   227       $xml .= $content;
       
   228       $xml .= "  </channel>";
       
   229       $xml .= "
       
   230 </rss>";
       
   231     }
       
   232     return $xml;
       
   233   }
       
   234   
       
   235 }
       
   236 
       
   237 // function names are IMPORTANT!!! The name pattern is: page_<namespace ID>_<page URLname, without namespace>
       
   238 
       
   239 function page_Special_RSS() {
       
   240   global $db, $session, $paths, $template, $plugins; // Common objects
       
   241   header('Content-type: text/xml; charset=windows-1252'); //application/rss+xml');
       
   242   $mode = $paths->getParam(0);
       
   243   $n = $paths->getParam(1);
       
   244   if(!preg_match('#^([0-9]+)$#', $n) || (int)$n > 50) $n = 20;
       
   245   else $n = (int)$n;
       
   246   switch($mode)
       
   247   {
       
   248     case "recent":
       
   249     case false:
       
   250       $title = getConfig('site_name') . ' Recent Changes';
       
   251       $desc = getConfig('site_desc');
       
   252       
       
   253       $rss = new RSS($title, $desc);
       
   254       
       
   255       $q = $db->sql_query('SELECT * FROM '.table_prefix.'logs WHERE log_type=\'page\' ORDER BY time_id DESC LIMIT '.$n.';');
       
   256       if(!$q)
       
   257       {
       
   258         $rss->add_item('ERROR', '', 'Error selecting log data: ' . mysql_error() . '', time());
       
   259       }
       
   260       else
       
   261       {
       
   262         while($row = $db->fetchrow())
       
   263         {
       
   264           $link = 'http' . ( isset($_SERVER['HTTPS']) ? 's' : '' ) . '://'.$_SERVER['HTTP_HOST'] . makeUrlNS($row['namespace'], $row['page_id']);
       
   265           $title = $paths->pages[$paths->nslist[$row['namespace']].$row['page_id']]['name'];
       
   266           $desc = ( $row['edit_summary'] != '' ) ? $row['edit_summary'] : 'No edit summary given.';
       
   267           $date = $row['time_id'];
       
   268           $guid = 'http' . ( isset($_SERVER['HTTPS']) ? 's' : '' ) . '://'.$_SERVER['HTTP_HOST'] . makeUrlNS($row['namespace'], $row['page_id']).'?oldid='.$row['time_id'];
       
   269           
       
   270           $rss->add_item($title, $link, $desc, $date, $guid);
       
   271         }
       
   272       }
       
   273       
       
   274       echo $rss->render();
       
   275       break;
       
   276     case "comments":
       
   277       $title = getConfig('site_name') . ' Latest Comments';
       
   278       $desc = getConfig('site_desc');
       
   279       
       
   280       $rss = new RSS($title, $desc);
       
   281       
       
   282       $q = $db->sql_query('SELECT * FROM '.table_prefix.'comments ORDER BY time DESC LIMIT '.$n.';');
       
   283         
       
   284       if(!$q)
       
   285       {
       
   286         $rss->add_item('ERROR', '', 'Error selecting log data: ' . mysql_error() . '', time());
       
   287       }
       
   288       else
       
   289       {
       
   290         $n = $db->numrows();
       
   291         //echo '<!-- Number of rows: '.$n.' -->'; // ."\n<!-- SQL backtrace: \n\n".$db->sql_backtrace().' -->';
       
   292         for ( $j = 0; $j < $n; $j++ )
       
   293         {
       
   294           $row = $db->fetchrow($q);
       
   295           if(!is_array($row)) die(__FILE__.':'.__LINE__.' $row is not an array');
       
   296           $link = 'http' . ( isset($_SERVER['HTTPS']) ? 's' : '' ) . '://'.$_SERVER['HTTP_HOST'] . makeUrlNS($row['namespace'], $row['page_id']).'#comments';
       
   297           $page = ( isset($paths->pages[$paths->nslist[$row['namespace']].$row['page_id']]) ) ? $paths->pages[$paths->nslist[$row['namespace']].$row['page_id']]['name'] : $paths->nslist[$row['namespace']].$row['page_id'];
       
   298           $title = $row['subject'] . ': Posted on page "'.$page.'" by user '.$row['name'];
       
   299           $desc = RenderMan::render($row['comment_data']);
       
   300           $date = $row['time'];
       
   301           $guid = 'http' . ( isset($_SERVER['HTTPS']) ? 's' : '' ) . '://'.$_SERVER['HTTP_HOST'] . makeUrlNS($row['namespace'], $row['page_id']).'?do=comments&amp;comment='.$row['time'];
       
   302           
       
   303           $rss->add_item($title, $link, $desc, $date, $guid);
       
   304         }
       
   305       }
       
   306       echo $rss->render();
       
   307       break;
       
   308     default:
       
   309       $code = $plugins->setHook('feed_me_request');
       
   310       foreach ( $code as $cmd )
       
   311       {
       
   312         eval($cmd);
       
   313       }
       
   314       break;
       
   315   }
       
   316 }
       
   317 
       
   318 ?>