[SPLIT] Re: MyStatus Mod (beta) - a social network extension for SMF 2.0

Started by SoLoGHoST, October 16, 2009, 01:30:40 AM

Previous topic - Next topic

ElectricSquid

Thanks soloGhost, for that code you posted, but it's laced with javascript and that confused the hell out of me :P

I'm now in the process of stripping down function ssi_boardNews for reuse.
It's coming along well so far, with no errors to speak of.
This outputs the first message for the 5 most recent topics (so far)

I'm still unsure on how to split the function so the database queries sit in Status.php, and the html resides in Status.template.php, so for the time being, I'm working on it all in one file.

Arantor

SMF is designed by nature on the idea of separating content from layout. Files in Sources/ get the data from the database and put it inside $context. They never display it or have any decision or impact on layout of that data. All they then do is load the template file with loadTemplate.

Then, the template file deals with display. It never bothers itself with where the data came from, just simply with displaying it.

ElectricSquid

OK, I thought that was the case.

So what you are saying is that there is an invisible wall between Sources/ files and their templates.
$context is the only way through that wall.

I just learned something today.

Can you give me a quick example how to define and pass data through $context?

Arantor

It's not an invisible wall per se, more a barrier of style. You can do it in a single file in sources, but it isn't recommended.

Sources:
$context['myvalue'] = 'something';

Template in Themes/
echo $context;

Have a look at my Buddy Page mod. It covers this interaction fairly simply IMO.

SoLoGHoST

Just wanna add in here that you have to have it defined as a global in both functions (in the source and in the template) or else it won't work.global $context;

RE-EDIT:  Apologize, I am wrong, $context must be used there.  But you can use $context to output an array of data... and do whatever with it in the template file.

Sorry bout that.  Don't know why I was thinking this.

ElectricSquid

Quote from: Arantor on October 16, 2009, 10:13:40 PM

Have a look at my Buddy Page mod. It covers this interaction fairly simply IMO.

I love the Buddy Page mod!!
That is a GREAT addition that fits in well with what I'm trying to do here.

Arantor


ElectricSquid

Cool, thanks!

At the top of BuddyPage.php, it says $context['linktree'][] =
What is the [] after ['linktree']?



$context['linktree'][] = array(
'url' => $scripturl . '?action=buddypage',
'name' => $txt['buddypage']


ElectricSquid

That worked.
I was able to successfully split the ssi_boardNews function.
It now displays for ?action=everyone
Only a few errors for lack of a language file FIXED


SoLoGHoST

Quote from: ∑£ℓ¢†®¡¢ §ợų¡đ on October 16, 2009, 10:43:41 PM
Cool, thanks!

At the top of BuddyPage.php, it says $context['linktree'][] =
What is the [] after ['linktree']?



$context['linktree'][] = array(
'url' => $scripturl . '?action=buddypage',
'name' => $txt['buddypage']



The [] just means to add it to the current $context['linktree'] array.  So it gets the current linktree and adds the name value after it as a hyperlink (with url defined).  If you don't define url in here, it will just be plain text.

Arantor

Correct.

Basically, $context['linktree'] is an indexed array (as opposed to a hashed array like $txt, or $context itself, meaning that $context['linktree'] has items of 0, 1, 2 etc.)

By using [] it just means add a new entry to the end of the array using the next lowest index value. This way it doesn't matter how many layers there are, you are always adding a new layer.

ElectricSquid

Here's the code I've been hacking down from ssi_boardNews.
I have it stripped down and error free (so far)

This code shows the first post in the most recent 12 topics.
What I am trying to do now is get it to return all the replies to each first post, along with the username and time of the reply. I've had many failed attempts, a few that were close, but still not right.

LOL, I've been working on this since 11am this morning, and finally have to give it up to get some rest.
Better luck tomorrow.

If you want to toss this on a devbox and take a look,
all 4 files needed for SMF 2.0 RC1.2 are attached below.

This is the offending code from Status.php that has kicked my @$$ all day :P


<?php
/**********************************************************************************
* Status.php                                                                      *
***********************************************************************************

if (!defined('SMF'))
die('Hacking attempt...');

/* This file is what shows the MyStatus Mod functions



*/

// Lets start with the main Everyone page accessed by ?action=everyone
function Everyone($board 118$limit 12$length null)
{
global $scripturl$db_prefix$txt$settings$modSettings$context;
global $smcFunc;

loadLanguage('Status');

// =====================
// ADMIN OPTIONS - start
// =====================

// Must be integers....

// What board does MyStatus Mod connect to
// This will be an admin setting in the future

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

// How many status updates (topics) get/show on the page
// This setting counts topics only, not replies
// This will be an admin setting in the future

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

// How long should the post be
// This will be an admin setting in the future

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

$limit max(0$limit);

// ====================
// ADMIN OPTIONS - end
// ====================


// Find the post ids.
$request $smcFunc['db_query']('''
SELECT id_first_msg
FROM {db_prefix}topics
WHERE id_board = {int:current_board}' 
. ($modSettings['postmod_active'] ? '
AND approved = {int:is_approved}' 
'') . '
ORDER BY id_first_msg DESC
LIMIT ' 
$limit,
array(
'current_board' => $board,
'is_approved' => 1,
     )
);
$status_updates = array();
while ($row $smcFunc['db_fetch_assoc']($request))
$status_updates[] = $row['id_first_msg'];
$smcFunc['db_free_result']($request);

if (empty($status_updates))
return array();

// Find the posts.
// I will do more with num_replies in the future

$request $smcFunc['db_query']('''
SELECT m.body, IFNULL(mem.real_name, m.poster_name) AS poster_name, m.poster_time,
t.num_replies, t.id_topic, m.id_member, m.smileys_enabled, m.id_msg, t.locked
FROM {db_prefix}topics AS t
INNER JOIN {db_prefix}messages AS m ON (m.id_msg = t.id_first_msg)
LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = m.id_member)
WHERE t.id_first_msg IN ({array_int:post_list})
ORDER BY t.id_first_msg DESC
LIMIT ' 
count($status_updates),
array(
'post_list' => $status_updates,
     )
);
$return = array();
while ($row $smcFunc['db_fetch_assoc']($request))
{
// If we want to limit the length of the post.
// I will add a collapse feature in the future for
// those giganta-posts some members make.
// Something like a [more] button to see the full post

if (!empty($length) && $smcFunc['strlen']($row['body']) > $length)
{
$row['body'] = $smcFunc['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'] = $smcFunc['substr']($row['body'], 0$cutoff);
$row['body'] .= '...';
}

$row['body'] = parse_bbc($row['body'], $row['smileys_enabled'], $row['id_msg']);


// Lets censor out the bad words for the children
censorText($row['body']);

$return[] = array(
'id' => $row['id_topic'],
'message_id' => $row['id_msg'],
'time' => timeformat($row['poster_time']),
'timestamp' => forum_time(true$row['poster_time']),
'body' => $row['body'],
'href' => $scripturl '?topic=' $row['id_topic'] . '.0',
'link' => '<a href="' $scripturl '?topic=' $row['id_topic'] . '.0">' $row['num_replies'] . ' ' . ($row['num_replies'] == $txt['status_comment'] : $txt['status_comments']) . '</a>',
'replies' => $row['num_replies'],
'comment_href' => !empty($row['locked']) ? '' $scripturl '?action=post;topic=' $row['id_topic'] . '.' $row['num_replies'] . ';num_replies=' $row['num_replies'],
'comment_link' => !empty($row['locked']) ? '' '<a href="' $scripturl '?action=post;topic=' $row['id_topic'] . '.' $row['num_replies'] . ';num_replies=' $row['num_replies'] . '">' $txt['status_write_comment'] . '</a>',
'new_comment' => '<a href="' $scripturl '?action=post;topic=' $row['id_topic'] . '.' $row['num_replies'] . '">' $txt['status_write_comment'] . '</a>',
'poster' => array(
'id' => $row['id_member'],
'name' => $row['poster_name'],
'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['poster_name'] . '</a>' $row['poster_name']
),
'locked' => !empty($row['locked']),
'is_last' => false
);


}
$smcFunc['db_free_result']($request);

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

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


  
$context['status_first_post'] = $return;
 

loadTemplate('Status''template_main');
}
?>





SoLoGHoST

You should look at how Display.php does this and follow their example.  Just remember, you only need to call upon the database just 1 time to get it all, than do a LIMIT on how many you need.

Sorry, I can only help you, I don't have the time to code it for you, as I have my plate full!!

Arantor

I'll admit I glanced over the code without reading it thoroughly.

The way to approach this - to get the 12 most recent threads, with all their replies - is as follows.

1. Query smf_topics, SELECT id_topic FROM {db_prefix}topics ORDER BY id_topic DESC LIMIT 12. This will fetch the ids of the top 12 most recently created topics. Add a WHERE id_board = clause if necessary.

2. Query smf_messages, SELECT * FROM {db_prefix}messages WHERE id_topic IN (list of ids we already have)

3. Iterate through this query and build an array in $context[id_topic][id_msg][stuff] of all the data given the columns in your query.


SoLoGHoST's suggestion of looking at Display.php is prudent however note that they have a callback system and it's applied on a single thread only.

ElectricSquid

That was my thought exactly.
I've been looking all in Display.php today trying to figure out what it is I need to extract. There's a lot of extra stuff in Display I don't need.

The one thing I'd need to figure out is how to get the second topic to display on the page.
Display.php creates a page with all the posts from one topic.
For this mod, I need to pull all the replies from up to 12 or more topics.

Quote from: SoLoGHoST on October 17, 2009, 11:16:10 PM

Sorry, I can only help you, I don't have the time to code it for you, as I have my plate full!!

Not a problem. This is how I learn.
I get myself way in over my head, and figure it out as I go.
The tips you guys have given me have kept me from getting stuck dead in the water.
Thanks a lot!!

ElectricSquid

I saw that "callback" and wondered what it that was.

Thanks Arantor, I'll take that info you gave me and apply it tomorrow morning.
By tomorrow night, I might have this looking like something :P

ElectricSquid

While rooting through Display.php, I saw something similar to what you suggested.

Quote
SELECT (*) FROM {db_prefix}messages

Is * a wildcard?

SoLoGHoST

* means to select all columns in the table.  Yeah, apologize for that.  Display.php does use a callback which gets all posts from id_msg = id_first_msg to id_last_msg sorting it by posts per page, start value, etc..  Which makes this much quicker with only 1 database query.  So if you find yourself hitting the database over the head 1 too many times (as I have), you may want to consider a callback function to get the values from it that you need.  In any case if you are just needing the last 12 posts, than use LIMIT 12 and order it by what Arantor stated.

Well, I'm outta here...

Good Luck with your mod :)

Arantor

Yes, * does mean all columns.

But if I understood you right, and you want last 12 topics with all their posts, it's two DB queries.

I think you can avoid using their callback function here, too.

ElectricSquid

Yes, you are correct.
I'm looking for about 12 topics total on one page.
For each topic, all of it's replies will show too.

For normal forum topics, this could be database suicide to show so much on one page.
But because this mod deals more with right now, now right now, and leaves older topics behind, I think the amount of comments (replies) per topic should be short enough to limit the strain on the database.

That's just a guess, but I'm banking on it.

Advertisement: