blob: 0c54f6f03d33012c63763c7cd1572671cd1977f3 [file] [log] [blame]
<?php
/* Copyright (c) 2010 Obeo.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Obeo - initial API and implementation
*/
// Limits the number of items that is to be displayed to the first n
$limitItem = 5;
// Limits the length of the displayed items' title to the first n characters
// -1 means the title length will not be limited
$limitTitleLength = -1;
// Limits the length of the displayed items' content to the first n characters
// -1 means the description will not be limited
// 0 Disables the description altogether
$limitDescriptionLength = 0;
// See http://www.php.net/manual/en/function.date.php for date formats
// Here, we use "June 1st, 2010" for example
$dateFormat = "F jS, Y";
class RSS2HTML {
var $readError;
function convert($feedURL, $feedLink) {
GLOBAL $limitItem;
GLOBAL $limitTitleLength;
GLOBAL $limitDescriptionLength;
GLOBAL $dateFormat;
$result = "";
$xmlString = $this->readFeed($feedURL);
if ($xmlString === FALSE) {
$result = $this->readError;
return $result;
}
$xmlParser = xml_parser_create();
$rssParser = new RSSParser();
xml_set_object($xmlParser, $rssParser);
xml_set_element_handler($xmlParser, "startElement", "endElement");
xml_set_character_data_handler($xmlParser, "characterData");
$parseResult = xml_parse($xmlParser, $xmlString, TRUE);
if ($parseResult == 0) {
$result = xml_error_string(xml_get_error_code($xmlParser));
$result .= "\nat ".xml_get_current_line_number($xmlParser);
$result .= ":".xml_get_current_column_number($xmlParser);
return $result;
}
$itemCount = min($limitItem, count($rssParser->items));
if ($itemCount > 0) {
// $feedLink = $rssParser->feed->link;
// // Custom fix for planet Acceleo : we don't have the accurate link
// $feedLink = "http://www.acceleo.org/planet/rss20.xml";
$feedTitle = $rssParser->feed->title;
$result = "<h6><a class='rss' href='$feedLink'><img align='right' src='images/rss2.gif' alt='RSS Feed'/></a>";
$result .= "<a href='$feedLink'>$feedTitle</a></h6>\n";
$result .= "<div class=\"modal\">\n<ul>\n";
for ($i = 0; $i < $itemCount; $i++) {
$item = $rssParser->items[$i];
$itemTitle = $this->limitLength($item->title, $limitTitleLength);
// Custom fix for planet Acceleo : trim the title up to the first ":"
$itemTitle = trim(substr(strstr($itemTitle, ":"), 1));
$itemDescription = "";
if ($limitDescriptionLength > 0) {
$itemDescription = $this->limitLength($item->description, $limitDescriptionLength);
}
$itemPubDate = date($dateFormat, $item->pubDate_time);
$result .= "<li>\n";
$result .= "<a href='$item->link' display='block'>$itemTitle</a><br/>\n";
if (strlen($itemDescription) > 0) {
$result .= "$itemDescription<br/>\n";
$result .= "<span class='posted'>$itemPubDate</span><br/>\n";
$result .= "<a href='$item->link'>read more...</a><br/>\n";
} else {
$result .= "<span class='posted'>$itemPubDate</span><br/>\n";
}
$result .= "</li>\n";
}
$result .= "</ul>\n</div>\n";
}
return $result;
}
/*
* Reads the feed denoted by URL $feedURL in memory.
*/
function readFeed($feedURL) {
// GLOBAL $feedURL;
if (strpos($feedURL, "http") === 0) {
$parsedURL = parse_url($feedURL);
$host = $parsedURL['host'];
$path = $parsedURL['path'];
$result = "";
$ip = gethostbyname($host);
$handle = fsockopen($ip, 80, $errno, $errstr, 10);
if(!$handle) {
$this->readError = $errstr;
return FALSE;
}
$httpRequest = "GET ".$path." HTTP/1.1\r\n";
$httpRequest .= "Host: ".$host."\r\n";
$httpRequest .= "User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-us; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3\r\n";
$httpRequest .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";
$httpRequest .= "Accept-Language: en-us,en;q=0.8,fr;q=0.5,fr-fr;q=0.3\r\n";
$httpRequest .= "Keep-Alive: 115\r\n";
$httpRequest .= "Connection: keep-alive\r\n";
$httpRequest .= "Referer: http://".$host."\r\n";
$httpRequest .= "\r\n";
fputs($handle, $httpRequest);
// Read the very first line of the header in order to retrieve the HTTP response code
$firstHeaderLine = fgets($handle, 1024);
$headerParts = explode(" ", $firstHeaderLine);
if ($headerParts[1] < 200 || $headerParts[1] >= 300) {
$this->readError = "HTTP ERROR: ".$headerParts[1];
@fclose($handle);
return FALSE;
}
$data = fread($handle, 16384);
while (!feof($handle)) {
$result .= $data;
$data = fread($handle, 16384);
}
fclose($handle);
// strip headers out of the result
$pos = strpos($result, "\r\n\r\n");
$result = substr($result, $pos + 4);
} else {
return file_get_contents($feedURL);
}
return $result;
}
/*
* Limit the length of the given HTML String to the given number of characters. Take note that this will strip all html information
* out of the text and only return the raw text itself (save for xml entities).
*/
function limitLength($initialValue, $limit = -1) {
if ($limit == -1 || strlen($initialValue) <= $limit) {
return $initialValue;
}
$result = "";
$pruneChar = FALSE;
for ($i = 0; $i < strlen($initialValue) && strlen($result) <= $limit; $i++) {
if (!$pruneChar && $initialValue[$i] == "<") {
$pruneChar = TRUE;
} elseif ($pruneChar && $initialValue[$i] == ">") {
$pruneChar = FALSE;
} else if (!$pruneChar) {
$result .= $initialValue[$i];
}
}
$lastSpace = strrchr($result, ' ');
if ($lastSpace != FALSE) {
$result = substr($result, 0, -strlen($lastSpace));
$result .= " [...]";
}
return $result;
}
}
class RSSParser {
var $tag = "";
var $currentItem = NULL;
var $insideChannel = FALSE;
var $insideItem = FALSE;
var $feed;
var $items = Array();
function startElement($parser, $tagName, $attrs) {
$this->tag = $tagName;
if ($tagName == "ITEM") {
$this->insideItem = TRUE;
$this->currentItem = new RSSItem();
} elseif ($tagName == "CHANNEL") {
$this->insideChannel = TRUE;
$this->feed = new Feed();
}
}
function endElement($parser, $tagName) {
$this->tag = "";
if ($tagName == "ITEM") {
$this->currentItem->pubDate = trim($this->currentItem->pubDate);
$this->currentItem->title = trim($this->currentItem->title);
$this->currentItem->description = trim($this->currentItem->description);
$this->currentItem->link = trim($this->currentItem->link);
$this->currentItem->author = trim($this->currentItem->author);
$this->currentItem->pubDate_time = strtotime($this->currentItem->pubDate);
$this->items[] = $this->currentItem;
$this->insideItem = FALSE;
} elseif ($tagName == "CHANNEL") {
$this->feed->title = trim($this->feed->title);
$this->feed->link = trim($this->feed->link);
$this->insideChannel = FALSE;
}
}
function characterData($parser, $data) {
if ($data != NULL && $data != "" && ($this->insideItem || $this->insideChannel)) {
switch ($this->tag) {
case "TITLE":
if ($this->insideItem) {
$this->currentItem->title .= $data;
} else if ($this->insideChannel) {
$this->feed->title .= $data;
}
break;
case "DESCRIPTION":
if ($this->insideItem) {
$this->currentItem->description .= $data;
}
break;
case "LINK":
if ($this->insideItem) {
$this->currentItem->link .= $data;
} else if ($this->insideChannel) {
$this->feed->link .= $data;
}
break;
case "PUBDATE":
$this->currentItem->pubDate .= $data;
break;
case "AUTHOR":
$this->currentItem->author .= $data;
break;
default:
}
}
}
}
class Feed {
var $title = "";
var $link = "";
}
class RSSItem {
var $title = "";
var $description = "";
var $link = "";
var $pubDate = "";
var $pubDate_time = 0;
var $author = "";
}
?>