PunBB modification – Implementing iconized categories for forum topics

PunBB is one of the fastest and minimal forum softwares powered by PHP. PunBB says about itself:

PunBB is a fast and lightweight PHP-powered discussion board. It is released under the GNU General Public License. Its primary goals are to be faster, smaller and less graphically intensive as compared to other discussion boards. PunBB has fewer features than many other discussion boards, but is generally faster and outputs smaller, semantically correct XHTML-compliant pages.

You can see a detailed review about PunBB from forum-software.org.

What’s the purpose this mod?

PunBB has categories for forum. But there is no categorization for Topics like many other forums. This mod implements an iconized category for topics. The end result of this mod is –

  • It will add an excellent looking “Category Icons” fieldset in “Post new topic” form. (see Image#1)
  • Users can (optionally) select a topic category while posting a topic.
  • The category icon will be displayed beside the topic title in forum index page, topic detail page, search result etc. (see Image#2 and Image#3)
  • Clicking on a category icon will show all topics under that category.(see Image#4)

Lets see some screenshot of this modification :

Category icons in "Post new topic" form

Image#1:  Category icons in Post new topic form

Category icons before topic title in forum page

Image#2: Category icons before topic title in forum page

FireShot Pro capture #5 - 'User Contributed Deals _ Television is poluting our culture' - local_deals_com_forum_viewtopic_php_id=5

Image#3: Category icon in topic page

FireShot Pro capture #7 - 'User Contributed Deals _ Search results' - local_deals_com_forum_search_php_search_id=1345131291

Image#4: Filtering by category

Let’s start

I am assuming the objective and the screenshots have eluded you if you are reading up to this, so let’s start. It’s assumed that you’ve at least some working experience on PHP (don’t mind if you’re a guru) and already installed PunBB. So, now we will start straight from modifying our working PunBB. First of all, download necessary files from below and extract it.

Download files : Topic categories for PunBB

This zip file contains –

  1. PHP file to modify database : install_topic_category.php file
  2. Sql file for sample data : sample_data.sql file
  3. Sample category icons : cat-icons folder
  4. Edited files : modified-files folder

Note: sample icons are taken from http://forums.slickdeals.net/. Thanks to slickdeals.

Now we will complete the modification in 6 easy steps. The files in modified-files folder of the downloaded package are taken from PunBB 1.2.2 just after implementing this modification. It will be easier to find and modify if you keep open the modified  file when changing your copy.

1. Modify database

After extracting files, copy the install_topic_category.php to your PunBB root folder and go to http://<path_of_punbb_root>/install_topic_category.php from browser. It will create new table <db_prefix>topic_categories and new field cat_id in <db_prefix>topics table. To insert sample topic categories, run the queries of sample_data.sql.  Then copy the cat-icons folder to <punbb_root>/img.

Note : Before executing the queries, change the word <table_prefix> as your table prefix.

Note : All your category icons should keep in <punbb_root>/img/cat-icons folder.

2. Add categories field to “Post new topic” form

Open post.php file.

Find this line (line: 35)

$fid = isset($_GET['fid']) ? intval($_GET['fid']) : 0;

Add this line below

$topic_category = isset($_POST['t_cat_id']) ? intval($_POST['t_cat_id']) : 0;
Find this query (line 289):
else if ($fid)
        {
            // Create the topic
            $db->query('INSERT INTO '.$db->prefix.'topics (poster, subject, posted, last_post, last_poster, forum_id) VALUES(''.$db->escape($username).'', ''.$db->escape($subject).'', '.$now.', '.$now.', ''.$db->escape($username).'', '.$fid.')') or error('Unable to create topic', __FILE__, __LINE__, $db->error());
and replace the query with this line:
            $db->query('INSERT INTO '.$db->prefix.'topics (poster, subject, posted, last_post, last_poster, forum_id, cat_id) VALUES(''.$db->escape($username).'', ''.$db->escape($subject).'', '.$now.', '.$now.', ''.$db->escape($username).'', '.$fid.', '.$topic_category.')') or error('Unable to create topic', __FILE__, __LINE__, $db->error());
Now add the fieldset in form. Find this line (line: 505)
$checkboxes = array();
if (!$pun_user['is_guest'])
{

Add this code just above the “$checkboxes = array();”

if ($fid): ?>
                <fieldset>
                    <legend>Category(optional)</legend>
                    <div class="infldset">
                        You may choose a category icon for your message from the following list:<br>
                        <div class="rbox">
                            <?php
                            $cat_result = $db->query('SELECT * FROM '.$db->prefix.'topic_categories') or error('Unable to fetch topic category list', __FILE__, __LINE__, $db->error());
                            while ($cur_topic_cat = $db->fetch_assoc($cat_result)):
                            ?>
                            <span class="topic-cat">
                                <input type="radio" value='<?php echo $cur_topic_cat['id']?>' name="t_cat_id">
                                <img src="<?php echo PUN_ROOT . 'img/cat-icons/' .$cur_topic_cat['cat_icon'] ?>" alt="<?php echo $cur_topic_cat['cat_name']?>" align="top"">
                            </span>
                            <?php endwhile; ?>
                            <div style="clear:both; height: 0px">&nbsp;</div>
                        </div>
                    </div>
                </fieldset>
<?php
endif;

Almost done. Just add this css to your template’s css file or put in header.php after line 80. Use <style> tag to add this in header.php

DIV.cat-icon {
    width: 47;
    height: 16;
    margin: 0px 5px;
    FLOAT: left;
    DISPLAY: block;
    border: none;
}
span.topic-cat{
    display: block;
    float: left;
    width: 100px;
    padding: 2px;
}
span.topic-cat input{
    margin-right: 2px;
}
span.topic-cat img{
    @margin-top: 3px;
}

Now you should see a fieldset in your form like Image#1.

Verify this change: Go to “Post new topic” page and see if their is a fieldset containing  category icons. Post a topic with selecting the category “Media”. Check the <prefix>topics table in database. ’11’ should be the value of cat_id field for last topic.

3. Display category icon in topic list

To display category icons in topic list, we have to modify 3 lines in viewforum.php.

Open the viewforum.php and find this lines (line:110)

if ($pun_user['is_guest'] || $pun_config['o_show_dot'] == '0')
{
    // Without "the dot"
    $sql = 'SELECT id, poster, subject, posted, last_post, last_post_id, last_poster, num_views, num_replies, closed, sticky, moved_to FROM '.$db->prefix.'topics WHERE forum_id='.$id.' ORDER BY sticky DESC, '.(($cur_forum['sort_by'] == '1') ? 'posted' : 'last_post').' DESC LIMIT '.$start_from.', '.$pun_user['disp_topics'];

Change the query of line 113 with this:

$sql = 'SELECT  t.id, poster, subject, posted, last_post, last_post_id, last_poster, num_views, num_replies, closed, sticky, moved_to,
                tc.id as t_cat_id, tc.cat_name, tc.cat_icon
          FROM  '.$db->prefix.'topics as t
                LEFT JOIN '.$db->prefix.'topic_categories AS tc ON t.cat_id=tc.id
         WHERE  forum_id='.$id.'
         ORDER  BY sticky DESC, '.(($cur_forum['sort_by'] == '1') ? 'posted' : 'last_post').' DESC
         LIMIT  '.$start_from.', '.$pun_user['disp_topics'];

And, Just after 7 lines of this change, the query below “‘case ‘mysqli’:” change with this one:

$sql = 'SELECT  p.poster_id AS has_posted,
                t.id, t.subject, t.poster, t.posted, t.last_post, t.last_post_id, t.last_poster, t.num_views, t.num_replies, t.closed, t.sticky, t.moved_to,
                tc.id as t_cat_id, tc.cat_name, tc.cat_icon
        FROM    '.$db->prefix.'topics AS t
                LEFT JOIN '.$db->prefix.'posts AS p ON t.id=p.topic_id AND p.poster_id='.$pun_user['id'].'
                LEFT JOIN '.$db->prefix.'topic_categories AS tc ON t.cat_id=tc.id
         WHERE  t.forum_id='.$id.'
         GROUP  BY t.id
         ORDER  BY sticky DESC, '.(($cur_forum['sort_by'] == '1') ? 'posted' : 'last_post').' DESC
         LIMIT  '.$start_from.', '.$pun_user['disp_topics'];

If your database is sqlite, you have to change the query below “case ‘sqlite’:” instead of the above.

Now find this line: (line: 221 originally/226 after applying changes above.)

<div class="<?php echo $icon_type ?>"><div class="nosize"><?php echo trim($icon_text) ?></div></div>

Add this lines below

<?php if(!empty($cur_topic['cat_icon'])): ?>
<div class="cat-icon">
    <a href="<?php echo 'search.php?action=show_cat&t_cat_id='. $cur_topic['t_cat_id'] ?>"><img src="<?php echo PUN_ROOT . 'img/cat-icons/' .$cur_topic['cat_icon'] ?>" alt="<?php echo $cur_topic['cat_name']?>" title="<?php echo $cur_topic['cat_name']?>"></a>
</div>
<?php endif; ?>

Ok, Done. Now if you go to index of a forum, you should see category icons at the left side of topics(for whose category icon was selected) as shown in image#2.

Verify this change: Go to the forum index in which you have posted a new topic in previous step. See if there is an icon of media before the new topic title.

4. Display category icon in Topic details page

Now we will change in viewtopic.php to show icons in topic page.

Open the file and go to this line (line: 96)

// Fetch some info about the topic
if (!$pun_user['is_guest'])
There is two queries at line 98 and line 100. First, replace the query of line 98 with this:
$result = $db->query('SELECT  t.subject, t.closed, t.num_replies, t.sticky,
                              f.id AS forum_id, f.forum_name, f.moderators,
                              fp.post_replies,
                              s.user_id AS is_subscribed,
                              tc.id as t_cat_id, tc.cat_name, tc.cat_icon
                        FROM  '.$db->prefix.'topics AS t
                              INNER JOIN '.$db->prefix.'forums AS f ON f.id=t.forum_id
                              LEFT JOIN '.$db->prefix.'subscriptions AS s ON (t.id=s.topic_id AND s.user_id='.$pun_user['id'].')
                              LEFT JOIN '.$db->prefix.'forum_perms AS fp ON (fp.forum_id=f.id AND fp.group_id='.$pun_user['g_id'].')
                              LEFT JOIN '.$db->prefix.'topic_categories AS tc ON t.cat_id=tc.id
                       WHERE  (fp.read_forum IS NULL OR fp.read_forum=1)
                              AND t.id='.$id.'
                              AND t.moved_to IS NULL')
or error('Unable to fetch topic info', __FILE__, __LINE__, $db->error());

And replace the other query (used for else) with the query below:

$result = $db->query('SELECT  t.subject, t.closed, t.num_replies, t.sticky,
                              f.id AS forum_id, f.forum_name, f.moderators,
                              fp.post_replies, 0,
                              tc.id as t_cat_id, tc.cat_name, tc.cat_icon
                        FROM  '.$db->prefix.'topics AS t
                              INNER JOIN '.$db->prefix.'forums AS f ON f.id=t.forum_id
                              LEFT JOIN '.$db->prefix.'forum_perms AS fp ON (fp.forum_id=f.id AND fp.group_id='.$pun_user['g_id'].')
                              LEFT JOIN '.$db->prefix.'topic_categories AS tc ON t.cat_id=tc.id
                       WHERE  (fp.read_forum IS NULL OR fp.read_forum=1)
                              AND t.id='.$id.'
                              AND t.moved_to IS NULL')
or error('Unable to fetch topic info', __FILE__, __LINE__, $db->error());

Find this line (Line: 315 originally/ 339 after applying the changes above)

<h2><span><span class="conr">#<?php echo ($start_from + $post_count) ?>&nbsp;</span><a href="viewtopic.php?pid=<?php echo $cur_post['id'].'#p'.$cur_post['id'] ?>"><?php echo format_time($cur_post['posted']) ?></a></span></h2>

Replace with this lines:

<h2>
    <span>
        <span class="conr">#<?php echo ($start_from + $post_count) ?>&nbsp;</span><a href="viewtopic.php?pid=<?php echo $cur_post['id'].'#p'.$cur_post['id'] ?>"><?php echo format_time($cur_post['posted']) ?></a>
        <?php if(!isset($category_printed) && !empty($cur_topic['cat_icon'])): ?>
            <a href="<?php echo 'search.php?action=show_cat&t_cat_id='. $cur_topic['t_cat_id'] ?>"><img align="top" src="<?php echo PUN_ROOT . 'img/cat-icons/' .$cur_topic['cat_icon'] ?>" alt="<?php echo $cur_topic['cat_name']?>" title="<?php echo $cur_topic['cat_name']?>"></a>
        <?php
        $category_printed = true;
        endif;
        ?>
    </span>
</h2>

You will see the category icon after the posting time in topic details page after applying the changes above as shown in Image#3.

Verify this change: Click on a the topic title which you posted in step 2. In the details page of the topic, check there is an icon of media after posting time of first post of topic.

5. Display category icon in search result

Here we will change the search.php so that icons appears in the listing of search result. First open the search.php and go to line 462. Replace the query of else block with:

$sql = 'SELECT  t.id AS tid, t.poster, t.subject, t.last_post, t.last_post_id, t.last_poster, t.num_replies, t.closed, t.forum_id,
                            tc.id as t_cat_id, tc.cat_name, tc.cat_icon
                      FROM  '.$db->prefix.'topics AS t
                            LEFT JOIN '.$db->prefix.'topic_categories AS tc ON t.cat_id=tc.id
                     WHERE  t.id IN('.$search_results.')
                     ORDER  BY '.$sort_by_sql;

Find this line of search.php  (line: 644 originally/650 after applying changes above.)

<div class="tclcon">
Add the following snippet  above this line:
<div class="cat-icon">
    <a href="<?php echo 'search.php?action=show_cat&t_cat_id='. $search_set[$i]['t_cat_id'] ?>"><img src="<?php echo PUN_ROOT . 'img/cat-icons/' . $search_set[$i]['cat_icon'] ?>" alt="<?php echo $search_set[$i]['cat_name']?>" title="<?php echo $search_set[$i]['cat_name']?>"></a>
</div>

Ok. Now you should see Category Icons in search result as other pages.

6. Filtering (or displaying) by category

At last, we will make icons enable for filtering. After completing this step, if you click on a category icon, it will show all topics which were posted under this topic category. This change will also happen in search.php.

Find this line in search.php (line 85)

// If it's a user search (by id)
else if ($action == 'show_user')

Add the following elseif block after ending of this elseif :

else if ($action == 'show_cat')
{
    $topic_cat_id = intval($_GET['t_cat_id']);
    if ($topic_cat_id < 1)
        message($lang_common['Bad request']);
}

Find this line (Line: 321 originally/ 327 after applying the changes above)

else if ($action == 'show_new' || $action == 'show_24h' || $action == 'show_user' || $action == 'show_subscriptions' || $action == 'show_unanswered')

And replace with this line:

else if ($action == 'show_new' || $action == 'show_24h' || $action == 'show_user' || $action == 'show_subscriptions' || $action == 'show_unanswered' || $action == 'show_cat')

Find this line (Line: 344 originally/ 350 after applying the changes above)

// If it's a search for posts by a specific user ID
else if ($action == 'show_user')

Add the following elseif block after closing of this elseif :

else if ($action == 'show_cat')
{
    $result = $db->query('SELECT  t.id
                            FROM  '.$db->prefix.'topics AS t
                                  INNER JOIN '.$db->prefix.'forums AS f ON f.id=t.forum_id
                                  LEFT JOIN '.$db->prefix.'forum_perms AS fp ON (fp.forum_id=f.id AND fp.group_id='.$pun_user['g_id'].')
                           WHERE  (fp.read_forum IS NULL OR fp.read_forum=1)
                                  AND t.cat_id='.$topic_cat_id.' GROUP BY t.id')
                   or error('Unable to fetch topic list', __FILE__, __LINE__, $db->error());
    $num_hits = $db->num_rows($result);

    if (!$num_hits)
        message($lang_search['No user posts']);
}

Everything is done. Now your icons are enabled to filtering topics.

Verify this change : Post 3 topics under 3 different forum with same topic category. And, from anywhere click on this category icon. Now you should see these 3 topics together as image#4.

We’re finished implementing Topic categories for PunBB. You can ask me anything about this modification. I will try my best to reply. Thanks a lot for staying this l-o-n-g time with ajaxray.

26 Comments

  1. Wow, that’s quite a bit of work and looks like a great addition to the excellent punBB forum. I love punBB for its simplicity and would always welcome new addition to it.

    Great work!

  2. 🙁 If you know, how to do this. Please send to PM. We need help Look at in the g oogle, but can’t find any info about this software. Please help. Best regards

  3. Nothing seems to be easier than seeing someone whom you can help but not helping.
    I suggest we start giving it a try. Give love to the ones that need it.
    God will appreciate it.

  4. @MM1

    Hi friend,
    The Zip file was somehow removed from server!
    Thanks a lot for informing.

    I’ve put it there. Now you can download it.

    Thanks again.

  5. This look interesting,so far.
    If it’s not just all bots here, let me know. I’m looking to network
    Oh, and yes I’m a real person LOL.

    See ya,

  6. Hi nto All
    My PC worked slowly, too much mistakes and buggs. Help me, please to fix buggs on my computer.
    I used Win Vista.
    Thx,
    neattepay

  7. Hello, as you may already noted I am fresh here.
    I will be happy to get any help at the start.
    Thanks and good luck everyone! 😉

  8. This can be a real wonderful reference that you will be supplying and you also give it away for free. I like viewing websites in which comprehend on-line involving supplying a excellent reference without cost. I really beloved looking at your post. Thank you!

Leave a Comment

Your email address will not be published. Required fields are marked *