RSS LJ

February 3, 2005

How to implement friends-only ()

by fluffy at 12:42 AM
Okay, so some of you are probably wondering how I implemented friends-only functionality in MT.

It's actually pretty simple, though it requires that you're using phpBB as your MT comments engine. It also has a few subtle implementation details which will probably not go over so well for the faint of heart.

2/3, 8:10 AM Fixed a silly bug where users pending authorization were able to see the entry too. Also, made it so locked entries don't include the category list.

The first thing to do is to create a phpBB user group called "friends," and a forum set to "private (hidden)" which is set to only be visible/postable to users in that group. I have the group set to "open" (which still requires confirmation from me to allow users in) but you may want to set it even tighter, such as "closed" or "private" ("closed" means that you have to initiate adding them into the group, and "private" means that random strangers can't even see who's in it unless they're in the group already).

Next, edit your common page header (the one which includes the various thread display functions and so on), and add these lines just before the final ?>:

// See if they're in the friends group
$query = $db->sql_query("SELECT group_id FROM " . USER_GROUP_TABLE . " WHERE group_id=(GROUP_ID) AND user_pending=0 AND user_id=" . $display_userdata['user_id']);
$user_friend = $db->sql_fetchrow($query);
Replace the (GROUP_ID) with the numerical ID of the group (which you can see by going to the group edit page and looking at the URL); for example, on my forum, it's "364." (The number is that high because every user gets their own group for some reason.)

What this code does is gives every page a global PHP variable called $user_friend which indicates whether the currently logged-in user is a member of the friends group.

Create a new MT category called "friends" (or similar).

In your GetForum module, change the parameter for the forum ID to this:

("<$MTEntryCategory$>" == "friends")?(FRIENDS_FORUM_ID):(NORMAL_FORUM_ID)
where (FRIENDS_FORUM_ID) indicates the forum ID of the friends-only forum, and (NORMAL_FORUM_ID) indicates the forum ID of the existing forum. (On my weblog they are 13 and 11, respectively.) Don't change any other parameters. If you chose a name other than "friends" for the MT category, change it in that code as well.

At this point, you should post a test entry in the "friends" category and make sure that the thread is created in the friends-only forum, and post another test entry in some other category and make sure that its thread is created in the normal forum. Post a few comments. Notice how they don't show up on the weblog.

The reason they don't show up is because of one of the unfortunate hacks which was necessary to make the forum post bot work to begin with. (The integration layer actually has two sessions active, the real session for the user and then a fake "virtual" session for the forum bot.) In your thread display function, add the following lines of code, just after the line which starts with global:

global $userdata;
$userdata = $display_userdata;
At this point, comments should display for users who are in the friends group, but shouldn't display for anyone else.

Now, the really important thing: making the entry itself only show up for friends. This bit is rather tricky.

I really, really hope you're using a template module for your entries' titles or headers or whatever. Here's a simplified version of mine, before this modification:

<h3 class="title">< href="<$MTEntryPermalink$>"><$MTEntryTitle$></a> (<MTEntryCategories glue=", "><a href="<$MTCategoryArchiveLink$>"><$MTCategoryLabel$></a></MTEntryCategories>)</h3>
and after:
<? $restrict = ("<$MTEntryCategory$>" == "friends") && !$user_friend; ?>
<h3 class="title">< href="<$MTEntryPermalink$>"><?
if ($restrict) { ?>
(private entry)</a>
<? } else { ?>
<$MTEntryTitle$></a> (<MTEntryCategories glue=", "><a href="<$MTCategoryArchiveLink$>"><$MTCategoryLabel$></a></MTEntryCategories>)
<? } ?>
</h3>
<? if ($restrict) { ?>
This is a private entry. If you would like to be allowed access, go to the forum and request to be added to the <a href="/forum/groupcp.php?g=364">friends group</a>.
<? } else { ?>
The first thing you should do (after making sure that the category name matches, just like before) is customize that message to direct people to the appropriate place to request addition to the group; at the very least you'll need to fix the group ID (and possibly the forum location), but if you've set the group to private or closed you'll want to give them a link for sending a private message to you instead, or whatever.

The other thing you should notice is that there's now an open { without a mate. This needs to be closed. What I did was created another template module called "End" which just contains

<? } ?>
and I call that template module after every use of the title module (making sure that any tags which open after the title module are closed before the end module). In the case of my weblog, this meant editing a few index templates, the individual archive template, and my template modules for short and tiny entries.

The reason I did it as a module was so that I could easily add more complicated entry-footer stuff later if I wanted. I probably won't, but you never know. (And anyway, it semantically matches better with the template module which starts each entry, even if it's more to type.)

Anyway. At this point, you should create a test user, browse your weblog to make sure everything works (and the test post doesn't show up), add the test user to the friends group, browse some more and make sure that your test post works, and then, well, that's it.

Some final notes: when setting an entry friends-only, you must set "friends" as the primary category. I could make the code detect if any category is "friends" (it's pretty simple, really) but it would be rather ugly, and anyway, this adds an extra layer of protection so that you won't have a few precious minutes where the entry is visible between you posting it and you adding the secondary categories.

Also, if you decide to make a non-friends entry friends-only later, remember to move the thread to the friends-only forum (and vice-versa).

One more useful thing which this can do that other weblogging software can't: you can make parts of individual entries friends-only, or display differently for friends vs. non-friends. It's actually pretty easy, and only requires a little tiny bit of PHP knowledge. Basically, to make a friends-only block you'd do something like:

<? if ($user_friend) { ?>
(insert friends-only stuff here)
<? } ?>
and if you want it to display differently for friends vs. non-friends, it's only slightly more complex:
<? if ($user_friend) { ?>
(insert friends version here)
<? } else { ?>
(insert non-friends version here)
<? } ?>
So, this isn't just a cheap hack to shoehorn LiveJournal-like functionality into MT+phpBB — it actually provides something that no other weblogging software does (as far as I know, anyway).

Comments

#4433 02/03/2005 02:31 pm If you feel that I'm worthy ...
... please add me to the friends group.

Regards,

-lm
#4434 02/03/2005 02:41 pm
Of course I do.
#4438 02/03/2005 05:04 pm
I'm not sure if this is the right way to ask, but I'll follow big fat idiot's steps. Can you add me to the fiends group?
#4441 02/03/2005 06:16 pm
broken
I'm not sure if this is the right way to ask, but I'll follow big fat idiot's steps. Can you add me to the fiends group?


The WHAT group?!
#4443 02/03/2005 07:11 pm
When you go to the groups page, doesn't it have a nice big button to send me a private message?

It'd be nice if phpBB separated the 'visible to everyone' and the 'anyone can apply for membership' functionality. I don't want the group contents to be there for everyone to see, but I also would much rather have the 'join group' button which is great (I get a little email, I go to the groups page, and I can mass accept/deny everyone who asked to join).
#4446 02/03/2005 07:29 pm
Okay, I've hacked on phpBB to allow open registration requests on hidden groups. Yay me.

--- groupcp.php.orig    2005-02-03 19:14:17.827853838 -0800
+++ groupcp.php 2005-02-03 19:22:38.825052434 -0800
@@ -222,7 +222,8 @@
 
        if (    $row = $db->sql_fetchrow($result) )
        {
-               if ( $row['group_type'] == GROUP_OPEN )
+               if ( $row['group_type'] == GROUP_OPEN
+                       | $row['group_type'] == GROUP_HIDDEN )
                {
                        do
                        {
@@ -858,7 +859,8 @@
        }
        else
        {
-               if ( $group_info['group_type'] == GROUP_OPEN )
+               if ( $group_info['group_type'] == GROUP_OPEN
+                    | $group_info['group_type'] == GROUP_HIDDEN )
                {
                        $template->assign_block_vars('switch_subscribe_group_input', array());