FRIHOST FORUMS SEARCH FAQ TOS BLOGS COMPETITIONS
You are invited to Log in or Register a free Frihost Account!


Outside phpBB Integration Functions





Aredon
So I've had a couple people around here ask me about some of the phpBB functions I've used for integration in the past. So I decided to make a thread I which I could share those. Instead of having a handful of PMs to keep track of. (plus this way it might save some lucky googler some time Smile) At the moment this is purely for fetching post and topic information, I may add more later if people ask for them. Also, my apologies if some of the code blocks get rather large. Many of these functions aren't exactly simple, and until phpBB finishes their API for this sort of thing, this is the best I can do.

I should stress that I really don't intend this for beginners, it's meant primarily for mid-level php programmers like myself. However, if you are in over your head with it and need some help, ask.

First thing's first, we start with some code provided by phpBB's example. You will need this to access the session data for your forum, to tell if users are logged in, if posts exist, etc. You will also notice that I have added some strings to the $phpbb_root_path and $smilies_path variables, you can remove these. I needed them because I was doing this integration outside my phpbb folder.
Code:
/*
* home.php
* Description: example file for displaying latest posts and topics
* by battye (for phpBB.com MOD Team)
* September 29, 2009
*/
 
define('IN_PHPBB', true);
$path = $_SERVER['DOCUMENT_ROOT'];
$phpbb_root_path = (defined('PHPBB_ROOT_PATH')) ? PHPBB_ROOT_PATH : $path.'/community/';
$smilies_path = (defined('SMILIES_PATH')) ? SMILIES_PATH : $path.'/community/images/smilies/';
$phpEx = substr(strrchr(__FILE__, '.'), 1);
include($phpbb_root_path . 'common.' . $phpEx);
include($phpbb_root_path . 'includes/bbcode.' . $phpEx);
include($phpbb_root_path . 'includes/functions_display.' . $phpEx);
include($phpbb_root_path . 'includes/functions_posting.' . $phpEx);
 
// Start session management
$user->session_begin();
$auth->acl($user->data);
$user->setup('viewforum');


From there we arrive at one that's commonly asked for. Keep in mind this is my edit of the original phpBB function, so some of the paths will have to be changed (for example /community/ you might need to change to another folder). I also make no guarantees as to it's prettiness or functionality Razz. I'll do my best to comment editing places, but don't expect this to be plug and play.
Recent Posts
$search_limit parameter pulls only the number of posts specified, or 5 by default.
$filter_id parameter will cause it to show recent posts for whatever forum id you give it. (single id or a list)
usage: $recent_post_array = recent_posts($search_limit, $filter_id);
Code:

function recent_posts($search_limit=5,$filter_id=false){
global $phpbb_root_path, $phpEx, $user, $db, $config, $cache, $template, $auth;
$forum_id = array();
$allowed=$db->sql_in_set('t.forum_id', array_keys($auth->acl_getf('f_read', true)));
if($filter_id){
   if(is_int($filter_id) or is_string($filter_id)){$forums = 't.forum_id IN ('.$filter_id.')';}
   if(is_array($filter_id)){
      $forums = 't.forum_id IN (';
      $i=count($filter_id);
      foreach($filter_id as $id){
         if(strstr($allowed,(string)$id)){$forums.=$id;}
         if($i>1)$forums.=', ';
         $i--;
      }
      $forums.=')';
   }
}else{
   $forums=$allowed;
}
//$forum_id_where = create_where_clauses($forum_id, 'forum');
   $posts_ary = array(
     'SELECT'    => 'p.*, t.*, u.username, u.user_colour',
 
     'FROM'      => array(
         POSTS_TABLE     => 'p',
     ),
 
     'LEFT_JOIN' => array(
         array(
             'FROM'  => array(USERS_TABLE => 'u'),
             'ON'    => 'u.user_id = p.poster_id'
         ),
         array(
             'FROM'  => array(TOPICS_TABLE => 't'),
             'ON'    => 'p.topic_id = t.topic_id'
         ),
     ),
 
     'WHERE'     =>  $forums . '
                     AND t.topic_status <> ' . ITEM_MOVED . '
                     AND t.topic_approved = 1
                AND t.forum_id != 37', //This was my news forum id, feel free to change or remove
 
     'ORDER_BY'  => 'p.post_id DESC',
 );
 
 $posts = $db->sql_build_query('SELECT', $posts_ary);
 
$posts_result = $db->sql_query_limit($posts, $search_limit);
 
   while( $posts_row = $db->sql_fetchrow($posts_result) )
   {
      $topic_title       = $posts_row['post_subject'];
      $post_author       = get_username_string('full', $posts_row['poster_id'], $posts_row['username'], $posts_row['user_colour'],false,$path.'/community/memberlist.php?mode=viewprofile&amp;u='.$user->data['user_id']); //edit path as needed.
      $post_date          = $user->format_date($posts_row['post_time']);
      $post_link       = append_sid("/community/viewtopic.$phpEx", 'f=' . $posts_row['forum_id'] . '&amp;t=' . $posts_row['topic_id'] . '&amp;p=' . $posts_row['post_id']) . '#p' . $posts_row['post_id']; //edit path as needed
 
      $post_text = nl2br($posts_row['post_text']);
 
      $bbcode = new bbcode(base64_encode($bbcode_bitfield));       
      $bbcode->bbcode_second_pass($post_text, $posts_row['bbcode_uid'], $posts_row['bbcode_bitfield']);
 
      $post_text = smiley_text($post_text);
 
      $template->assign_block_vars('announcements', array(
      'TOPIC_TITLE'       => censor_text($topic_title),
      'POST_AUTHOR'       => $post_author,
      'POST_DATE'       => $post_date,
      'POST_LINK'       => $post_link,
      'POST_TEXT'         => censor_text($post_text),
      ));
   }
   return $template->_tpldata['announcements'];
}

This one I wrote myself, but it has pretty similar functionality to the one above. Please note the difference between topics and posts when using these functions Smile.

Hot Topics - This has had a major update, it now limits shown "hot topics" as the topics that have posts made within the last 30 days.
$search_limit parameter pulls only the number of posts specified, or 5 by default.
$filter_id parameter will cause it to show recent posts for whatever forum id you give it. (single id or a list)
usage: $hot_topics_array = hot_topics($search_limit, $filter_id);
Code:

function hot_topics($search_limit=5,$filter_id=false,$max_age=2592000){
   global $phpbb_root_path, $phpEx, $user, $db, $config, $cache, $template, $auth;
   $hot_count=5;// Define how many posts is "hot"
   $allowed=$db->sql_in_set('t.forum_id', array_keys($auth->acl_getf('f_read', true)));
if($filter_id){
   if(is_int($filter_id) or is_string($filter_id)){$forums = 't.forum_id IN ('.$filter_id.')';}
   if(is_array($filter_id)){
      $forums = 't.forum_id IN (';
      $i=count($filter_id);
      foreach($filter_id as $id){
         if(strstr($allowed,(string)$id)){$forums.=$id;}
         if($i>1)$forums.=', ';
         $i--;
      }
      $forums.=')';
   }
}else{
   $forums=$allowed;
}
    $sql = 'SELECT t.topic_id, t.forum_id, t.topic_title, t.topic_time, t.topic_replies, t.topic_views, u.username, u.user_id, u.user_colour, t.topic_poster
                    FROM ' . TOPICS_TABLE . ' t , ' . USERS_TABLE . ' u
                    WHERE t.topic_approved = 1
                        AND ' . $forums;   
   $sql.=' AND t.topic_replies >= ' . $hot_count . '
                  AND t.topic_poster = u.user_id';
   $sql.=' AND t.forum_id != 3'; // Don't pull from news! Dat's Silly!
   $age_calc = time() - $max_age;
   $sql.=' AND t.topic_last_post_time > '.$age_calc;
    $sql.=' ORDER BY t.topic_replies DESC, t.topic_time DESC
                    LIMIT 0, ' . $search_limit;
    $result = $db->sql_query($sql);
   $posts=array();
   $i=0;
   while($row = $db->sql_fetchrow($result)){
      $topics[$i]=$row;
      $topics[$i]['topic_date']=$user->format_date($row['topic_time']);
      $topics[$i]['author']=get_username_string('full', $row['user_id'], $row['username'], $row['user_colour'],false,$path.'/forum/memberlist.php?mode=viewprofile&amp;u='.$row['user_id']);
      $i++;
   }
   return $topics;
}


Lastly, my news feed function. For use only if you have some sort of news forum that you'd like to display outside the phpBB folder.
News Feed
Code:

function news_feed($search_limit=5,$forum_id=37){ // change 37 to your news forum id.
   global $phpbb_root_path, $phpEx, $user, $db, $config, $cache, $template, $auth;
   $forums = array_unique(array_keys($auth->acl_getf('f_read', true)));
    $sql = 'SELECT t.topic_id, t.forum_id, t.topic_title, t.topic_time, u.username, u.user_id, u.user_colour, t.topic_poster
                    FROM ' . TOPICS_TABLE . ' t , ' . USERS_TABLE . ' u
                    WHERE t.topic_approved = 1
                        AND ' . $db->sql_in_set('t.forum_id', $forums);
   if($forum_id)$sql.= ' AND t.forum_id = '.$forum_id;
   $sql.=' AND t.topic_poster = u.user_id
                    ORDER BY t.topic_time DESC
                    LIMIT 0, ' . $search_limit;
    $result = $db->sql_query($sql);
   $posts=array();
   $i=0;
   while($row = $db->sql_fetchrow($result)){
      $topics[$i]=$row;
      $topics[$i]['author']=get_username_string('full', $row['user_id'], $row['username'], $row['user_colour'],false,$path.'/community/memberlist.php?mode=viewprofile&amp;u='.$user->data['user_id']); //edit path as needed
      $i++;
   }
   return $topics;
}


Who is Online
This handy little thing will let you display who is online on other pages outside the forum Very Happy.

Code:

function display_online(){
   global $user, $config;
   $users_online = obtain_users_online();
   $users_online_string = obtain_users_online_string($users_online);
   $l_online_record = sprintf($user->lang['RECORD_ONLINE_USERS'], $config['record_online_users'], $user->format_date($config['record_online_date']));
## Feel free to edit any of the echos below to your liking, format the html as needed.
   echo '<a href="/forum/viewonline.php">Who is Online</a>:<hr />';
    echo $users_online_string['l_online_users'].'<br />';
     echo    $l_online_record.'<br /><br />';
       echo str_replace('/home/USER/domains/YOURDOMAIN/public_html/','/',$users_online_string['online_userlist']); //this was a necessary path fix, you will need to edit it or find another way around it. If you don't your user links will simply 404.
}


That's all I have for now, I'll be editing and throwing more in here based on feedback or additional requests. Thanks for reading! Enjoy! Smile
Fire Boar
Now then, I would be very impressed if you could come up with a way to input a sequence of post data arrays, and as a result store the posts correctly, with the correct timestamp and user id.

I ask because I've found that phpBB has such a shoddy API that creating posts as someone else is impossible without delving into the source and rewriting large chunks of existing code. If you can figure out a way to do that, you deserve a medal!
Aredon
There's already a pretty simple way to input posts that I've used for integration in the past. Let me look up that function and get back to you. I do recall that it was slightly complicated to figure out, but once i got it working it was easy. Smile
Aredon
phpBBroot/includes/functions_posting.php (or include the module I posted in the first post, it includes this file)
Quote:

submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $update_message = true, $update_search_index = true)
Source: line 1628 functions_posting.php

Example usage:
Code:

$data = array(
         'poster_id' => 2,
         'forum_id' => 2,
         'topic_id' => 2,
         'mode' => post,
         'icon_id' => false,
         'post_approved' => false,
         'enable_bbcode' => true,
         'enable_smilies' => true,
         'enable_urls' => true,
         'enable_sig' => true,
         
         'message' => $message,
         'message_md5' => md5($message),
         
         'bbcode_bitfield' => $bitfield,
         'bbcode_uid' => $uid,
         
         'post_edit_locked' => 0,
         'topic_title' => $subject,
         'notify_set' => false,
         'notify' => false,
          'post_time' => 0,
         'forum_name' => '',
         'enable_indexing' => true,         
      );
There are various other settings that can be added or removed from the data array, you'll have to check phpBB's wiki (or read the function) to find more. (for example $data['force_approved_state'] = false)
Code:
submit_post($mode, $subject, '', POST_NORMAL, $poll, $data);


enjoy! Very Happy
Fire Boar
Unfortunately... line 1603 in my version...

Code:
$poster_id = ($mode == 'edit') ? $data['poster_id'] : (int) $user->data['user_id'];


Also, line 1635-1658 (1639 being the line of interest):

Code:
        case 'post':
        case 'reply':
            $sql_data[POSTS_TABLE]['sql'] = array(
                'forum_id'            => ($topic_type == POST_GLOBAL) ? 0 : $data['forum_id'],
                'poster_id'            => (int) $user->data['user_id'],
                'icon_id'            => $data['icon_id'],
                'poster_ip'            => $user->ip,
                'post_time'            => $current_time,
                'post_approved'        => $post_approval,
                'enable_bbcode'        => $data['enable_bbcode'],
                'enable_smilies'    => $data['enable_smilies'],
                'enable_magic_url'    => $data['enable_urls'],
                'enable_sig'        => $data['enable_sig'],
                'post_username'        => (!$user->data['is_registered']) ? $username : '',
                'post_subject'        => $subject,
                'post_text'            => $data['message'],
                'post_checksum'        => $data['message_md5'],
                'post_attachment'    => (!empty($data['attachment_data'])) ? 1 : 0,
                'bbcode_bitfield'    => $data['bbcode_bitfield'],
                'bbcode_uid'        => $data['bbcode_uid'],
                'post_postcount'    => ($auth->acl_get('f_postcount', $data['forum_id'])) ? 1 : 0,
                'post_edit_locked'    => $data['post_edit_locked']
            );
        break;


Lines 1705-1721 are similar. I've already been there, if it were that easy I wouldn't be offering a medal. Wink Basically this function relies on the $user global variable being set, and the User and Session classes that $user is an instance of depend on session variables, meaning creating a different instance of User or Session is extremely tricky to do. That kinda defeats the point of having an object in the first place really.
Aredon
Actually no, you can set anything about the post. The author, the subject, the message, the forum id, the topic id, the post id. Session vars only take over as default values. Don't edit the function itself, just call it and put the $data array you want it to follow.
Fire Boar
Wrong, I'm afraid. Trace carefully through the code or simply try using it and you'll see that in submit_post the $data['poster_id'] is ignored for new topics. It's only used for editing, so that the "edited by X for reason Y" message appears. As I said before, if it were that simple I wouldn't be offering a medal.
Aredon
hmm then it pulls poster from the $user->data array right? Maybe you could do something like this to sort of hack your way around it:
Code:

$temp=$user->data['user_id']; //Store this for restore later
$user->data['user_id'] = 42; //desired user_id for post
submit_post($data);
$user->data['user_id'] = $temp;


Not sure if that'll work... just rattling it off the top of my head.
Aredon
I just found out not that long ago, that the $user->data spoof does indeed work for submit_post() with a different user. Here's an example:

Code:
function submit_app($post){
   global $db, $user, $auth;
   //foreach($post as $name => $value){
   //}
   $subject = "test post2!";
   $message = 'test post!';
   // Backup User ID for spoof
   $o_user_id = $user->data['user_id'];
    $o_user_ip = $user->ip;
   // Set user_id for the bot
    $user_id = '228';
    // Create the spoof
   $sql = 'SELECT *
      FROM ' . USERS_TABLE . '
            WHERE user_id = ' . $user_id;
   $result = $db->sql_query($sql);
   $row = $db->sql_fetchrow($result);
   $db->sql_freeresult($result);

   $user->data = array_merge($user->data, $row);
   $auth->acl($user->data);
   $user->ip = '0.0.0.0';
   ############################################
   $message = utf8_normalize_nfc($message);     
   $poll = $uid = $bitfield = $options = '';
    generate_text_for_storage($subject, $uid, $bitfield, $options, false, false, false);
    generate_text_for_storage($message, $uid, $bitfield, $options, true, true, true);
    $topic_type = POST_NORMAL;
   $data = array(
        'forum_id'        => 17,
      'forum_name'      => 'Guild Applications',
        'icon_id'        => false,

        'enable_bbcode'        => true,
        'enable_smilies'    => true,
        'enable_urls'        => true,
        'enable_sig'        => true,

        'message'        => $message,
        'message_md5'    => md5($message),
               
        'bbcode_bitfield'    => $bitfield,
        'bbcode_uid'        => $uid,

        'post_edit_locked'    => 0,
        'topic_title'        => $subject,
        'notify_set'        => false,
        'notify'            => false,
        'post_time'         => 0,
        'enable_indexing'    => true,
        'topic_time_limit' => 0,
        'topic_approved' => true,
      'force_approved_state' => true,
    );
     submit_post('post', $subject, '', POST_NORMAL, $poll, $data);
   // set original user back!
   $sql = 'SELECT *
      FROM ' . USERS_TABLE . '
            WHERE user_id = ' . $o_user_id;
   $result = $db->sql_query($sql);
   $row = $db->sql_fetchrow($result);
   $db->sql_freeresult($result);

   $user->data = array_merge($user->data, $row);
   $auth->acl($user->data);

   //Overwrite users IP to normal
   $user->ip = $o_user_ip;
}


Do I win? Cool
Fire Boar
You do indeed, sir. Smile Congratulations. However, I'd propose revising that code a little, because re-fetching the old user data each time isn't a great plan. Use the clone method instead. If we're lucky, that should work too.

Code:
function submit_app($subject, $message, $user_id) {
  global $db, $user, $auth;

  // Backup User ID for spoof
  $o_user = clone $user;
  $o_auth = clone $auth;
  // Create the spoof
  $sql = 'SELECT * FROM ' . USERS_TABLE . ' WHERE user_id = ' . $user_id;
  $result = $db->sql_query($sql);
  $row = $db->sql_fetchrow($result);
  $db->sql_freeresult($result);

  $user->data = array_merge($user->data, $row);
  $auth->acl($user->data);
  $user->ip = '0.0.0.0';

  $message = utf8_normalize_nfc($message);     
  $poll = $uid = $bitfield = $options = '';
  generate_text_for_storage($subject, $uid, $bitfield, $options, false, false, false);
  generate_text_for_storage($message, $uid, $bitfield, $options, true, true, true);
  $topic_type = POST_NORMAL;
  $data = array(
    'forum_id'   => 17,
    'forum_name' => 'Guild Applications',
    'icon_id'    => false,

    'enable_bbcode'  => true,
    'enable_smilies' => true,
    'enable_urls'    => true,
    'enable_sig'     => true,

    'message'     => $message,
    'message_md5' => md5($message),

    'bbcode_bitfield' => $bitfield,
    'bbcode_uid'      => $uid,

    'post_edit_locked'     => 0,
    'topic_title'          => $subject,
    'notify_set'           => false,
    'notify'               => false,
    'post_time'            => 0,
    'enable_indexing'      => true,
    'topic_time_limit'     => 0,
    'topic_approved'       => true,
    'force_approved_state' => true,
  );
  submit_post('post', $subject, '', POST_NORMAL, $poll, $data);

  // set original user back!
  $user = $o_user;
  $auth = $o_auth;
}
Aredon
You forgot the $user_id for the bot Razz, aside from that I think clone should work... The only thing I can think of that would prevent it from working would be the session id, but I can't imagine that the session would change. I'll play with it later, in the meantime, it works Smile.

My current project is actually "who is online" status updates for pages outside of the board, and I'll probably add that to my main post when I find the time. Smile
Fire Boar
Not sure what you mean with $user_id... I'm passing it as an argument in my code sample: I might want multiple bots, or to post as an actual user.

The session ID was the only sticking point I could think of too (hence "if we're lucky"). This is where PHPBB3 sucks. The code is all over the place. If PHPBB were properly coded, the function would look more like this:

Code:
function submit_post($subject, $message, $user) {
  $post = new Post();
  $post->setAuthor($user);
  $post->setSubject($subject);
  $post->setMessage($message);
  return $post->save();
}


Where $user is an instance of the User class, which would be built in such a way that it's possible to have any number of $users at a time.
Aredon
Ahh you have $user_id as a parameter, didn't see that. My mistake. (/gasp post #666!)
Aredon
Well time for a thread update. I've created my who is online function, and edited my hot topics function a decent amount. I'll be adding them shortly. Smile

Here's what it looks like on my site. Very Happy

I'm now also running a fully functional phpBB posting bot within my own forum using the code we discussed earlier. Can create posts from forms on other pages not seen by the original poster. Pretty handy if you plan on using phpBB as a CMS system!

Also of note I created a function to help with tracking posts submitted by these bots. It's pretty simple honestly.
Code:
function extract_param($a_string){ //works with submit_post to extract the parameters from the return string.
   $a_string=preg_split('/\/viewtopic.php\?/',$a_string);
   $a_string[1]=html_entity_decode($a_string[1]);
   $a_string=preg_split('/&/', $a_string[1]);
   foreach($a_string as $string){
      $set=preg_split('/=/',$string);
      switch($set[0]){
         case 'f':
            $return['f']=$set[1];
            break;
         case 't':
            $return['t']=$set[1];
            break;
         case 'p':
            $return['p']=$set[1];
            break;
      }
   }
return $return;
}
Related topics
Olympus website integration
Expand collapse HTML Tag
Dynamic User Customizable Sites. CSS + PHP = Awesome!
phpBB Module for Hot, Random, and Recent Topics?
phpBB Session Integration
phpbb
My Heavily modded phpBB PreMod xD
Latest PHP install may cause phpBB to return errors...
[PHP] phpbb registration - add to other db
phpBB question
phpBB "integration"
PHP VS ASP
I'll Install A GCBoard For You! (Different board from phpBB)
Just uploaded. Shouldn't be jibberish.
Reply to topic    Frihost Forum Index -> Scripting -> Php and MySQL

FRIHOST HOME | FAQ | TOS | ABOUT US | CONTACT US | SITE MAP
© 2005-2011 Frihost, forums powered by phpBB.