News:

SMF 2.1.4 has been released! Take it for a spin! Read more.

Main Menu

can I access a single topic with SSI or RSS? [edit: yes]

Started by linear, February 17, 2005, 11:15:26 AM

Previous topic - Next topic

linear

I've pretty well convinced myself from looking at SSI.php that it's not possible that way, but I wanted to ask befor eI started messing with News.php.

I'm trying to use a single topic to host discussion on a single article, and while I can easily link to the topic from my article, it would be slick to have recent posts listed as well to spur interest in participating in the board.

So two questions:
1) is it already included functionality?
2) would it be easier to modify SSI.php or News.php (the SSI approach is probably  prefereable in my environment, although either one works for me)

I'm aiming to be able to get an RSS feed of a topic, in fhe form
h*p://forums.linear1.org/index.php?action=.xml;sa=recent;topic=52;limit=5;type=rss2

it looks like I'd need to write a function in News.php that implemented this (the SQL would be different, but mostly resembles getXmlRecent() with some changes to scope it down from a board to a topic), and then add it to the $subActions array in ShowXmlFeed(), right?

Is there a better way?

Owdy

Former Lead Support Specialist

Tarvitsetko apua SMF foorumisi kanssa? Otan työtehtäviä vastaan, lue:http://www.simplemachines.org/community/index.php?topic=375918.0

linear

Perhaps I'm not entirely clear on what that mod does, but I installed it and it seems to enhance SSI.php by adding a grabPost() function. What I'm after in those terms would be grabTopic().

linear

Okay, this function, when added to SSI.php does what I need:

// Show a specific topic, with a template.
function ssi_topicNews($topic = null, $limit = null, $start = null, $length = null, $output_method = 'echo')
{
global $scripturl, $db_prefix, $txt;
global $settings, $modSettings, $context;

loadLanguage('Stats');

// Must be integers....
if ($limit === null)
$limit = isset($_GET['limit']) ? (int) $_GET['limit'] : 5;
else
$limit = (int) $limit;

if ($start === null)
$start = isset($_GET['start']) ? (int) $_GET['start'] : 0;
else
$start = (int) $start;

if ($topic !== null)
$topic = (int) $topic;
elseif (isset($_GET['topic']))
$topic = (int) $_GET['topic'];

if ($length === null)
$length = isset($_GET['length']) ? (int) $_GET['length'] : 0;
else
$length = (int) $length;

// Make sure guests can see this topic.
$request = db_query("       
SELECT ID_TOPIC         
FROM {$db_prefix}topics as t, {$db_prefix}boards as b
WHERE " . ($topic === null ? '' : "ID_TOPIC = $topic
AND ") . "FIND_IN_SET(-1, memberGroups)
LIMIT 1", __FILE__, __LINE__);
if (mysql_num_rows($request) == 0)
{                           
if ($output_method == 'echo')
die($txt['smf_news_error2']);
else                   
return array();     
}                           
list ($topic) = mysql_fetch_row($request);
mysql_free_result($request);

// Find the posts.
$request = db_query("
SELECT
m.icon, m.subject, m.body, IFNULL(mem.realName, m.posterName) AS posterName, m.posterTime,
t.numReplies, t.ID_TOPIC, m.ID_MEMBER, m.smileysEnabled
FROM {$db_prefix}topics AS t, {$db_prefix}messages AS m
LEFT JOIN {$db_prefix}members AS mem ON (mem.ID_MEMBER = m.ID_MEMBER)
WHERE t.ID_TOPIC = $topic
AND m.ID_TOPIC = t.ID_TOPIC
ORDER BY m.ID_MSG DESC
LIMIT $start, $limit", __FILE__, __LINE__);
$return = array();
while ($row = mysql_fetch_assoc($request))
{
// If we want to limit the length of the post.
if (!empty($length) && strlen($row['body']) > $length)
{
$row['body'] = substr($row['body'], 0, $length);

// The first space or line break. (<br />, etc.)
$cutoff = max(strrpos($row['body'], ' '), strrpos($row['body'], '<'));

if ($cutoff !== false)
$row['body'] = substr($row['body'], 0, $cutoff);
$row['body'] .= '...';
}

$row['body'] = doUBBC($row['body'], $row['smileysEnabled']);

censorText($row['subject']);
censorText($row['body']);

$return[] = array(
'id' => $row['ID_TOPIC'],
'icon' => '<img src="' . $settings['images_url'] . '/post/' . $row['icon'] . '.gif" align="middle" alt="' . $row['icon'] . '" />',
'subject' => $row['subject'],
'time' => timeformat($row['posterTime']),
'timestamp' => $row['posterTime'],
'body' => $row['body'],
'href' => $scripturl . '?topic=' . $row['ID_TOPIC'] . '.0',
'link' => '<a href="' . $scripturl . '?topic=' . $row['ID_TOPIC'] . '.0">' . $row['numReplies'] . ' ' . ($row['numReplies'] == 1 ? $txt['smf_news_1'] : $txt['smf_news_2']) . '</a>',
'replies' => $row['numReplies'],
'new_comment' => '<a href="' . $scripturl . '?action=post;topic=' . $row['ID_TOPIC'] . '.' . $row['numReplies'] . '">' . $txt['smf_news_3'] . '</a>',
'poster' => array(
'id' => $row['ID_MEMBER'],
'name' => $row['posterName'],
'href' => !empty($row['ID_MEMBER']) ? $scripturl . '?action=profile;u=' . $row['ID_MEMBER'] : '',
'link' => !empty($row['ID_MEMBER']) ? '<a href="' . $scripturl . '?action=profile;u=' . $row['ID_MEMBER'] . '">' . $row['posterName'] . '</a>' : $row['posterName']
),
'is_last' => false
);
}
mysql_free_result($request);

if (empty($return))
return $return;

$return[count($return) - 1]['is_last'] = true;

if ($output_method != 'echo')
return $return;

foreach ($return as $news)
{
echo '
<table border="0" width="100%" align="center" class="ssi_table">
<tr>
<td>', $news['icon'], ' <b>', $news['subject'], '</b><span class="smaller"><br />', $news['time'], ' ', $txt[525], ' ', $news['poster']['link'], '<br /><br /></span></td>
</tr>
<tr>
<td>', $news['body'], '<br /><br /></td>
</tr>
<tr>
<td>', $news['link'], ' | ', $news['new_comment'], '</td>
</tr>
</table>
<br />';

if (!$news['is_last'])
echo '
<hr width="100%" />
<br />';
}
}


I completely understand that editing SSI.php is a Bad Idea. So how do I proceed to package this as a proper mod? Your assistance is appreciated.

(BTW, this was a fairly small tweak against the existing boardNews() function--the post mod didn't help me too much.)

[Unknown]

I would put this in a separate file like so:

<?php

include_once('/path/to/SSI.php');

// ... functions here ...

?>


And name it like "include.php" or something.

-[Unknown]

jbeezer

I've been searching the forums for quite some time trying to find a way to use SSI to pull out a specific topic and its replies.  This code does just that!  thanks linear. 

Idealy I'd like to have a better formatted output, in fact have the exact same output that that Display.template.php generates(atleast i think thats the file).  I'd love to have it appear just the topic does in the forum with quote, reply, karma, the whole works (minus the header and footer). Is it possible to write a function in SSI to do this?

linear

Hey, jbeezer, do you know about the $output_method feature of SSI functions? Since I cloned this function from a different one (just changed the SQL statement basically) it has full support for the array output method. You get an array $return that you can output in any fashion you choose, including what you want.

happy hacking.

jbeezer

Thanks for the quick reply.  Yea i know about it, but not all of the values that it contains.  I've found examples detailing how to use the array thats returned, but now the problem is, how can i find out what all the contents of the array are so that i can use them? 

$news['body']
$news['subject']
$news['poster']['link']

is there some place where i can see what all the names ('body', 'subject', etc) are?  Or will I have to write a loop to interate through it all and print it out to see?

edit:
ok im stupid, i looked at your code and saw where you fill the array, it looks like i need to modify the SQL query to return some additional data such as avatars, karma, post group

linear

Yeah, just pull the fields you need from the user table, then add new elements to the associative array $return[].

TestMonkey

#9
I have compiled the code submitted I believe originally by Sting for ssi_topicNews into a module
You can find it here in the mods download area.

Description:
Quote
Thank you for using ssi_topicNews Mod by TestMonkey.

This Mod is an updated and packaged version of the function originally posted and created by sting in this thread:
http://www.simplemachines.org/community/index.php?topic=78532.0

This Mod Adds a function that allows you to get and display a specific topic as an single story or article.

Example usage:
    ssi_topicNews($topic, $limit = null, $start = null, $length = null, $link = null, $output_method = 'array');

Changelog:
ssi_topicNews v0.5
- Cleaned up code a bit, updated the $length/$cutoff code to work correctly like how ssi_BoardNews() is done currently.
- Added new option $link, which allows you to pass a url into the function which generates a "Read More..." link.

ssi_topicNews v0.4
- Install Scripts now use install.mod and uninstall.mod so the package now cleanly uninstal's the modification.

ssi_topicNews v0.3
- Cleaned up the package install scripts

ssi_topicNews v0.2
- Added $board = null; to the function to eleminate errors in the forum logs.
- Added code to turn $topic into an integer
- Added code to default to $topic 2 which is the default first post if $topic 0 or 1 was defined

ssi_topicNews v0.1
- First release

TODO List:
- Keep Optimising the code in ssi_topicNews();
- Clean up the echo output_method formatting some.

Notes:
1) $topic 0 or 1 can not be selected, It will default to 2 the default SMF first post..
2) If you get an parse error while trying to install the mod, go into:
    Packages -> Options, and Change all file permissions throughout the forum such that:: All files are writable.
    -OR-
    Manually chmod SSI.php to 666 or 777 through an ftp program.
    Now try to apply the modification again and it should work.
3) If you use the $link variable it needs to point to the full story somewhere.

Keep in mind this mod is still actively being developed.
Understand it works fine now but will be improved greatly over the next few months.
For now it's still considered beta code.

The updated code that is in the module above.
Code (php) Select

// Show the latest news, with a template... by topic.
function ssi_topicNews($topic = null, $limit = null, $start = null, $length = null, $link = null, $output_method = 'echo')
{
global $scripturl, $db_prefix, $txt, $settings, $modSettings, $context, $func;

loadLanguage('Stats');

$board = null;

// Must be integers....
if ($topic == null)
$topic = (int) '2';
elseif($topic == '1')
$topic = (int) '2';
else
$topic = (int) $topic;

if ($limit === null)
$limit = isset($_GET['limit']) ? (int) $_GET['limit'] : 10;
else
$limit = (int) $limit;

if ($start === null)
$start = isset($_GET['start']) ? (int) $_GET['start'] : 0;
else
$start = (int) $start;

if ($board !== null)
$board = (int) $board;
elseif (isset($_GET['board']))
$board = (int) $_GET['board'];

if ($length === null)
$length = isset($_GET['length']) ? (int) $_GET['length'] : 0;
else
$length = (int) $length;

// Make sure guests can see this board.
$request = db_query("
SELECT ID_BOARD
FROM {$db_prefix}boards
WHERE " . ($board === null ? '' : "ID_BOARD = $board
AND ") . "FIND_IN_SET(-1, memberGroups)
LIMIT 1", __FILE__, __LINE__);
if (mysql_num_rows($request) == 0)
{
if ($output_method == 'echo')
die($txt['smf_news_error2']);
else
return array();
}
list ($board) = mysql_fetch_row($request);
mysql_free_result($request);

// Find the posts.
$request = db_query("
SELECT
m.icon, m.subject, m.body, IFNULL(mem.realName, m.posterName) AS posterName, m.posterTime,
t.numReplies, t.ID_TOPIC, m.ID_MEMBER, m.smileysEnabled
FROM ({$db_prefix}topics AS t, {$db_prefix}messages AS m)
LEFT JOIN {$db_prefix}members AS mem ON (mem.ID_MEMBER = m.ID_MEMBER)
WHERE t.ID_TOPIC = $topic
AND m.ID_MSG = t.ID_FIRST_MSG
ORDER BY m.ID_MSG DESC
LIMIT $start, $limit", __FILE__, __LINE__);
$return = array();
while ($row = mysql_fetch_assoc($request))
{
// If we want to limit the length of the post.
if (!empty($length) && $func['strlen']($row['body']) > $length)
{
$row['body'] = $func['substr']($row['body'], 0, $length);

// The first space or line break. (<br />, etc.)
$cutoff = max(strrpos($row['body'], ' '), strrpos($row['body'], '<'));

if ($cutoff !== false)
$row['body'] = $func['substr']($row['body'], 0, $cutoff);
$row['body'] .= '...';
if ($link !== null){
$row['body'] .= '<div class="smalltext" style="margin-top: 1ex; font-weight: bold;">';
$row['body'] .= '<a href="';
$row['body'] .= $link;
$row['body'] .= '" title="Full Story">Read more...</a>';
$row['body'] .= '</div>';
}
}

$row['body'] = parse_bbc($row['body'], $row['smileysEnabled'], $row['ID_MSG']);

// Check that this message icon is there...
if (empty($modSettings['messageIconChecks_disable']) && !isset($icon_sources[$row['icon']]))
$icon_sources[$row['icon']] = file_exists($settings['theme_dir'] . '/images/post/' . $row['icon'] . '.gif') ? 'images_url' : 'default_images_url';

censorText($row['subject']);
censorText($row['body']);

$return[] = array(
'id' => $row['ID_TOPIC'],
'icon' => '<img src="' . $settings['images_url'] . '/post/' . $row['icon'] . '.gif" align="middle" alt="' . $row['icon'] . '" />',
'subject' => $row['subject'],
'time' => timeformat($row['posterTime']),
'timestamp' => $row['posterTime'],
'body' => $row['body'],
'href' => $scripturl . '?topic=' . $row['ID_TOPIC'] . '.0',
'link' => '<a href="' . $scripturl . '?topic=' . $row['ID_TOPIC'] . '.0">' . $row['numReplies'] . ' ' . ($row['numReplies'] == 1 ? $txt['smf_news_1'] : $txt['smf_news_2']) . '</a>',
'replies' => $row['numReplies'],
'new_comment' => '<a href="' . $scripturl . '?action=post;topic=' . $row['ID_TOPIC'] . '.' . $row['numReplies'] . '">' . $txt['smf_news_3'] . '</a>',
'poster' => array(
'id' => $row['ID_MEMBER'],
'name' => $row['posterName'],
'href' => !empty($row['ID_MEMBER']) ? $scripturl . '?action=profile;u=' . $row['ID_MEMBER'] : '',
'link' => !empty($row['ID_MEMBER']) ? '<a href="' . $scripturl . '?action=profile;u=' . $row['ID_MEMBER'] . '">' . $row['posterName'] . '</a>' : $row['posterName']
),
'is_last' => false
);
}
mysql_free_result($request);

if (empty($return))
return $return;

$return[count($return) - 1]['is_last'] = true;

if ($output_method != 'echo')
return $return;

foreach ($return as $news)
{
echo '
<table border="0" width="100%" align="center" class="ssi_table">
<tr>
<td>', $news['icon'], ' <b><font color=white>', $news['subject'], '</b><br /><br /></font></td>
</tr>
<tr>
<td><b><font color=white>', $news['body'], '<br /><br /></font></b></td>
</tr>
<tr>
<td Align=Center><b><font color=white style="font-size: 11px">', $news['link'], ' | ', $news['new_comment'], '</font><font color=white style="font-size: 11px"> | </font><font color=#8585A9 style="font-size: 11px">', $news['time'], '</font><font color=white style="font-size: 11px"> | </font>', $news['poster']['link'], '</b></td>
</tr>
</table>';

if (!$news['is_last'])
echo '
<hr width="100%" />
<br />';
}
}


Example usage:
Code (php) Select

<?php
$ssi_gzip 
'true';
$ssi_ban 'true';
$ssi_layers = array('main');
$context['page_title'] = 'Article Example';

// Update this if SSI.php is located elsewhere
require(dirname(__FILE__) . '/SSI.php');
ob_start();

$action $_REQUEST['page'];
if(!
$action || empty($action)) {
    
$topic '2';
    
$page 'full';
    
$length '110';
    
$link $_SERVER['PHP_SELF'] . '?page=' $page;
    
$result ssi_topicNews($topic$limit null$start null$length$link$output_method 'array');
    foreach (
$result as $news)
    {
echo '
<div class="tborder">
<table cellpadding="4" cellspacing="0" border="0" width="100%" align="center">
<tr>
<td valign="middle" align="right" width="22">
'
$news['icon'], '
</td>
<td align="left" style="padding-left: 6px;">
<div style="font-family: Tahoma; line-height: 1.3em;">
 '
$news['subject'], '
</div>
</td>
</tr>
<tr>
<td colspan="2">
<div style="line-height: 1.3em; font-family: Tahoma;">
'
$news['body'], '
</div>
</td>
</tr>
<tr>
<td align="center" colspan="2">
<font style="font-size: 11px">'
$news['link'], ' | '$news['new_comment'], ' | '$news['time'], ' | '$news['poster']['link'], '</font>
</td>
</tr>
</table>
</div>
      '
;
    }
} elseif(
$action == 'full') {
    
$topic '2';
    
$result ssi_topicNews($topic$limit null$start null$length null$link null$output_method 'array');
    foreach (
$result as $news)
    {
echo '
<div class="tborder">
<table cellpadding="4" cellspacing="0" border="0" width="100%" align="center">
<tr>
<td valign="middle" align="right" width="22">
'
$news['icon'], '
</td>
<td align="left" style="padding-left: 8px;">
<div style="font-family: Tahoma; line-height: 1.3em;">
 '
$news['subject'], '
</div>
</td>
</tr>
<tr>
<td colspan="2">
<div style="line-height: 1.3em; font-family: Tahoma;">
'
$news['body'], '
</div>
</td>
</tr>
<tr>
<td align="center" colspan="2">
<font style="font-size: 11px">'
$news['link'], ' | '$news['new_comment'], ' | '$news['time'], ' | '$news['poster']['link'], '</font>
</td>
</tr>
</table>
</div>
'
;
    }
}

ssi_shutdown();
ob_end_flush();
?>


Will allow you to show a readmore link if current page is not ?page=full, you can alter this in many ways depending what you need to do.

Just note that you need to play with the $length value there, depending on how long or short you're target post is..

*Edited*
Improvements made to the code/mod, and adjusted the example code to reflect the changes.
Knowledge is power
www.serverhash.com

dmacdonald111

I am extremely interested in this mod. It is exactly what I am looking for, but it has not been approved yet. Do we have a time frame when this will be acheived? I am not too confident to change any files myself.

Thanks.

TestMonkey

#11
From what I understand it went into the mod approval queue on the 14th of feb, and is on a list of 100's of mod's so is just a matter of time.

Also if no body has thought of it yet the best use of this mod to me is allong side ssi_boardNews(), use ssi_BoardNews() to get a list of all the topics in a forum as links, then using the links with ssi_topicNews to access and display specific Topics etc..
I may add the ability to show all the replies and such as comments to be used with output_method('array') in the full article/story view..
But for now i'm focusing on the core code and the installer scripts etc.
Knowledge is power
www.serverhash.com

TestMonkey

Knowledge is power
www.serverhash.com

Advertisement: