<?php
// Copyright 2011 Toby Zerner, Simon Zerner
// This file is part of esoTalk. Please see the included license file for usage information.
// Feed controller: builds a list of items to be outputted as an RSS feed.
if (!defined("IN_ESOTALK")) exit;
class FeedController extends Controller {
// Feed data variables, outputted in the view.
var $items = array();
var $pubDate = "";
var $title = "";
var $description = "";
var $link = "";
function init()
{
global $language, $config, $messages;
// Change the root view so that the wrapper is not outputted.
$this->esoTalk->view = "feed.php";
header("Content-type: text/xml; charset={$language["charset"]}");
if ($return = $this->fireEvent("init")) return;
// Work out what type of feed we're doing, based on the URL:
// conversation/[id] -> fetch the posts in conversation [id].
// default -> fetch the most recent posts over the whole forum.
switch (@$_GET["q2"]) {
// Fetch the posts in a specific conversation.
case "conversation":
// Get the conversation details.
$conversationId = (int)$_GET["q3"];
if (!$conversationId or !($conversation = $this->esoTalk->db->fetchAssoc("SELECT c.conversationId AS id, c.title AS title, c.slug AS slug, c.private AS private, c.posts AS posts, c.startMember AS startMember, c.lastActionTime AS lastActionTime, GROUP_CONCAT(t.tag ORDER BY t.tag ASC SEPARATOR ', ') AS tags FROM " . config("esoTalk.database.prefix") . "conversations c LEFT JOIN " . config("esoTalk.database.prefix") . "tags t USING (conversationId) WHERE c.conversationId=$conversationId GROUP BY c.conversationId")))
$this->esoTalk->fatalError($messages["cannotViewConversation"]["message"]);
// Do we need authentication to view this conversation (ie. is it private or a draft)?
if ($conversation["private"] or $conversation["posts"] == 0) {
// Try to login with provided credentials.
if (isset($_SERVER["PHP_AUTH_USER"])) $this->esoTalk->login($_SERVER["PHP_AUTH_USER"], $_SERVER["PHP_AUTH_PW"]);
// Still not logged in? Ask them again!
if (!$this->esoTalk->user) {
header('WWW-Authenticate: Basic realm="esoTalk RSS feed"');
header('HTTP/1.0 401 Unauthorized');
$this->esoTalk->fatalError($messages["cannotViewConversation"]["message"]);
}
// We're logged in now. So, is this member actually allowed in this conversation?
if (!($conversation["startMember"] == $this->esoTalk->user["memberId"]
or ($conversation["posts"] > 0 and (!$conversation["private"] or $this->esoTalk->db->result("SELECT allowed FROM " . config("esoTalk.database.prefix") . "status WHERE conversationId=$conversationId AND (memberId={$this->esoTalk->user["memberId"]} OR memberId='{$this->esoTalk->user["account"]}')", 0))))) {
// Nuh-uh. Get OUT!!!
$this->esoTalk->fatalError($messages["cannotViewConversation"]["message"]);
}
}
// Past this point, the user is allowed to view the conversation.
// Set the title, link, description, etc.
$this->title = "{$conversation["title"]} - {$config["forumTitle"]}";
$this->link = $config["baseURL"] . makeLink($conversation["id"], $conversation["slug"]);
$this->description = $conversation["tags"];
$this->pubDate = date("D, d M Y H:i:s O", $conversation["lastActionTime"]);
// Fetch the 20 most recent posts in the conversation.
$result = $this->esoTalk->db->query("SELECT postId, name, content, time FROM " . config("esoTalk.database.prefix") . "posts INNER JOIN " . config("esoTalk.database.prefix") . "members USING (memberId) WHERE conversationId={$conversation["id"]} AND deleteMember IS NULL ORDER BY time DESC LIMIT 20");
while (list($id, $member, $content, $time) = $this->esoTalk->db->fetchRow($result)) {
$this->items[] = array(
"title" => $member,
"description" => sanitize($this->format($content)),
"link" => $config["baseURL"] . makeLink("post", $id),
"date" => date("D, d M Y H:i:s O", $time)
);
}
break;
// Fetch the most recent posts over the whole forum.
default:
// It doesn't matter whether we're logged in or not - just get non-deleted posts from conversations
// that aren't private!
$result = $this->esoTalk->db->query("SELECT p.postId, c.title, m.name, p.content, p.time FROM " . config("esoTalk.database.prefix") . "posts p LEFT JOIN " . config("esoTalk.database.prefix") . "conversations c USING (conversationId) INNER JOIN " . config("esoTalk.database.prefix") . "members m ON (m.memberId=p.memberId) WHERE c.private=0 AND c.posts>0 AND p.deleteMember IS NULL ORDER BY p.time DESC LIMIT 20");
while (list($postId, $title, $member, $content, $time) = $this->esoTalk->db->fetchRow($result)) {
$this->items[] = array(
"title" => "$member - $title",
"description" => sanitize($this->format($content)),
"link" => $config["baseURL"] . makeLink("post", $postId),
"date" => date("D, d M Y H:i:s O", $time)
);
}
// Set the title, link, description, etc.
$this->title = "{$language["Recent posts"]} - {$config["forumTitle"]}";
$this->link = $config["baseURL"];
$this->pubDate = !empty($this->items[0]) ? $this->items[0]["date"] : "";
}
}
// Format post content to be outputted in the feed.
function format($post)
{
global $config, $language;
$this->fireEvent("formatPost", array(&$post));
// Replace empty post links with "go to this post" links.
$post = preg_replace("`(<a href='" . str_replace("?", "\?", makeLink("post", "(\d+)")) . "'[^>]*>)<\/a>`", "$1{$language["go to this post"]}</a>", $post);
// Convert relative URLs to absolute URLs.
$post = preg_replace("/<a([^>]*) href='(?!http|ftp|mailto)([^']*)'/i", "<a$1 href='{$config["baseURL"]}$2'", $post);
$post = preg_replace("/<img([^>]*) src='(?!http|ftp|mailto)([^']*)'/i", "<img$1 src='{$config["baseURL"]}$2'", $post);
return $post;
}
}