Главная > Разное, Сайт > Кросспостинг из WordPress в PhpBB. Не забыть почитать руководство разработчика

Кросспостинг из WordPress в PhpBB. Не забыть почитать руководство разработчика

wp2phpbb

Несмотря на то, что форум здесь по большому счёту нахрен никому не нужен и используется мной как личный-публичный блокнот, когда-то начатая мной затея кросспостинга из блога в форум, кривая и неуклюжая, синхронно трудится здесь в паре с моим больным воображением.

Редкий постоянный посетитель давно заметил, что плагин к WordPress косячит, и "не понимает", что кросспостинг был выполнен ранее, и  продолжает загаживать форум на каждый чих.  Это было первой причиной, по которой я взялся править код.

А второй причиной стал мой давний разговор с Вадимом Стеркиным. Как-то вечером я втирал ему что-то про форум, и Вадим между дел отметил, что ему было бы интересно посмотреть на решение с интеграцией форума phpbb с движком WordPress, в частности,

  • создание темы на форуме синхронно с новым постом в блоге;
  • перелинковка с созданной темой;
  • отображение постов на форуме в виде комментариев к статье.

Я помню, в тот момент подобное мне показалась если не совсем простой, то вполне достижимой целью, и вчера ближе к полночи я решил порешать задачу и порешить баг.

И всё завертелось

Больше всего на свете, сука, я ненавижу разбираться в своем же коде. У меня профессиональные навыки настолько альтернативно развиты, что, открыв свой код полугодичной давности, я вхожу в ступор. Отделаться от ощущения, что это кривое полотно написали инопланетяне, а не ты, первые несколько минут очень сложно.

Да ну да ладно.

Я долго, но тщетно пытался откопать, что в моем коде могло сломаться. Во избежание повторного репоста я использовал метаданные поста WordPress и вызов функции update_post_meta из моего плагина. Очевидно, что-то было не так в королевстве Датском именно с метаданными.

Мой любимый способ отладки кода - гипноз. Я довольно долго гипнотизировал исходник, пытаясь понять, что я мог написать неправильно.

На первый, второй и третий взгляд всё было хорошо.

Я принялся за отладку, в процессе которой обнаружил, что update_post_meta перестает работать после подключения к базе данных форума.

Подозреваю, что ноги растут из-за вышедшего обновления  Wordpress 3.5.1, в котором добавлен мультиблоггинг, и которое я по лени накатил совсем недавно. Вероятно, ещё одно активное MySQL-подключение сводит update_post_meta функцию с ума. Равно как и фейлят и попытки использовать $wpdb->query();

В качестве временной меры я вынес установку метаданных до подключения к БД.

Конечно, это плохое решение, такое же плохое решение, как и реализация этого плагина. Умные люди обычно читают руководство разработчика WordPress, рекомендации плагинописателям и Release notes для ветки 3.5. А я открыл исходники WordPress...

"Я не стану думать об этом сейчас. Я подумаю об этом завтра"

и вспомнил Скарлетт О`Хара из "Унесенных ветром". Букв было много, времени до утра было мало, поэтому я успокоил себя (костыль воткнут, работает система) и завалился спать.

Я обещаю себе разобраться в вопросе, убрать костыль и показать уже Стеркину рабочий прототип. В конце-концов, мне это ещё и интересно.

Все заинтересованные личности могут посмотреть исходник ниже и усвоить для себя, как писать не надо:

<?php
/*
Plugin Name: wp2phpbb
Plugin URI: http://winreview.ru
Description: Cross-posting to phpbb forum.
Version: 1.5
Author: Happy Bulldozer
Author URI: http://winreview.ru
License: GPL2
*/
require('db.php');
require('config.php');

function wp2phpbb($post_ID)
{
    global $phpbb_dbhost,$phpbb_dbuser,$phpbb_dbpasswd,$phpbb_dbname;
    global $phpbb_user_id,$phpbb_user_name,$phpbb_user_ip,$phpbb_user_colour;
    global $phpbb_forum_id;

    $time = time();
     $post = get_post($post_ID);

    $phpbb_meta = intval(get_post_meta($post_ID, 'phpbb', true));
    if ($phpbb_meta == 0)
    {

        ///TODO: fix the shit
        update_post_meta($post_ID, 'phpbb',1);
        $phpbb_topic_title = $post->post_title;
        $link  = get_permalink($post_ID);
        $phpbb_post_text_ar= explode('<!--more-->', $post->post_content);
        $phpbb_post_text = '<span style="color: #0000FF"><span style="font-size: 150%; line-height: 116%;"><span style="font-weight: bold">'.$phpbb_topic_title.'</span></span></span><br />'.$phpbb_post_text_ar[0].'&nbsp;&nbsp;<a href="'.$link.'">Читать полностью...</a>';
        $phpbb_success=false;

        $phpbb=new db;
        if (!$phpbb->db_Connect($phpbb_dbhost , $phpbb_dbuser, $phpbb_dbpasswd , $phpbb_dbname))
        {
            die('forum connection failed');
        }

        $query = 'insert into phpbb_topics 
                    (forum_id,topic_approved,topic_title,topic_poster,topic_time,topic_views)
                    values
                    ('.$phpbb_forum_id.',1,\''.$phpbb_topic_title.'\','.$phpbb_user_id.','.$time.', 0)';
        $phpbb->db_Query($query,true);

        $phpbb_topic_id = $phpbb->LAST_ID;
        if ( $phpbb_topic_id > 0 )
        {
            $query = 'insert into phpbb_posts
            (topic_id,forum_id,poster_id,poster_ip,post_time,post_approved,
            post_username,post_text,post_subject,bbcode_uid,bbcode_bitfield)
            values ('.$phpbb_topic_id.','.$phpbb_forum_id.','.$phpbb_user_id.',\''.$phpbb_user_ip.'\','.$time.',1,
            \'\',\''.$phpbb_post_text.'\',\''.$phpbb_topic_title.'\',\'\',\'\')';
            $phpbb->db_Query($query,true);

            $phpbb_post_id = $phpbb->LAST_ID;    
            if ($phpbb_post_id>0)    
            {
                //recount num of replies and statistics
                $query = 'update phpbb_topics tp,
                (select topic_id,count(post_id)-1 as cnt from phpbb_posts where topic_id = '.$phpbb_topic_id.' group by topic_id) p 
                set topic_replies=p.cnt, topic_replies_real=p.cnt,
                topic_last_post_id = '.$phpbb_post_id.',
                topic_last_poster_id = '.$phpbb_user_id.',
                topic_first_post_id = '.$phpbb_post_id.',
                topic_first_poster_name = \''.$phpbb_user_name.'\',
                topic_first_poster_colour = \''.$phpbb_user_colour.'\',
                topic_last_poster_name = \''.$phpbb_user_name.'\',
                topic_last_poster_colour=\''.$phpbb_user_colour.'\',
                topic_last_post_time = '.$time.',
                topic_last_view_time = '.$time.',
                topic_views = 1
                where tp.topic_id=p.topic_id and tp.topic_id = '.$phpbb_topic_id;
                $phpbb->db_Query($query);

                //recount forums messages & statistics
                UpdateForumStats($phpbb, $phpbb_forum_id,$phpbb_post_id,$phpbb_user_id,$phpbb_user_name,$time,$phpbb_user_colour);            

                //user - post count & last visit
                $query = 'update phpbb_users pu, 
                (select poster_id,count(post_id) cnt from phpbb_posts where poster_id = '.$phpbb_user_id.' group by poster_id) pc
                set pu.user_posts=pc.cnt,
                user_lastvisit = '.$time.',
                user_lastpost_time = '.$time.'
                where pu.user_id=pc.poster_id and pu.user_id = '.$phpbb_user_id;
                $phpbb->db_Query($query);

                //pointless table
                $query = 'select count(topic_posted) cnt from phpbb_topics_posted where topic_id='.$phpbb_topic_id.' and user_id='.$phpbb_user_id;
                $phpbb->db_Query($query);
                $phpbb_topics_posted_row = $phpbb->db_Fetch();
                $phpbb_topics_posted = $phpbb_topics_posted_row['cnt'];
                if ($phpbb_topics_posted==0)
                {
                    $query = 'insert into phpbb_topics_posted (topic_id,user_id,topic_posted)
                    values ('.$phpbb_topic_id.','.$phpbb_user_id.',1)';
                    $phpbb->db_Query($query);
                }
                $phpbb_success=true;
                $phpbb->db_Close();
                unset($phpbb);
            }
            //add post_meta
            /*if ($phpbb_success)
            {
                update_post_meta(intval($post_ID), 'phpbb',intval($phpbb_topic_id));
            }*/            
        }//phpbb_topic_id check
    }//post meta check    
    return $post_ID;
}

function UpdateForumStats($osql, $pforum_id,$pforum_last_post_id,$pforum_last_poster_id,$pforum_last_poster_name,$pforum_last_post_time,$pposter_colour,$current_level=true)
{
    if($pforum_id>0)
    {

        $query='select parent_id,forum_posts,forum_topics,forum_topics_real from phpbb_forums where forum_id = '.$pforum_id;
        $osql->db_Query($query);
        $orow = $osql->db_Fetch();
        $parent_id = intval($orow['parent_id']);
        $forum_posts = intval($orow['forum_posts'])+1;
        $forum_topics = intval($orow['forum_topics'])+1;
        $forum_topics_real = intval($orow['forum_topics_real'])+1;

        $query='update phpbb_forums set '.
        ($current_level ? 'forum_posts='.$forum_posts.',' : '').
        ($current_level ? 'forum_topics_real='.$forum_topics_real.',' : '').
        ($current_level ? 'forum_topics='.$forum_topics.',' : '').'
        forum_last_post_id='.$pforum_last_post_id.',
        forum_last_poster_id='.$pforum_last_poster_id.',
        forum_last_poster_name=\''.$pforum_last_poster_name.'\',
        forum_last_post_time='.$pforum_last_post_time.' ,
        forum_last_poster_colour=\''.$pposter_colour.'\'
        where forum_id = '.$pforum_id;
        $osql->db_Query($query);
        //strange, but phpbb uses 'forum_posts' update only for current level
        UpdateForumStats($osql, $parent_id,$pforum_last_post_id,$pforum_last_poster_id,$pforum_last_poster_name,$pforum_last_post_time,$pposter_colour,false);
    }

}

function LoadSpecifiedForum($forum_id=0, $limit=5, $forum_url="http://winreview/forum/", $href_class="", $item_start="", $item_end="")
{
    global $dbhost,$dbuser,$dbpasswd,$dbname;
    $query="select topic_id,topic_title from phpbb_topics where forum_id=".$forum_id." ORDER BY topic_id DESC LIMIT 0,".$limit;
    $result = "";
    $phpbb=new db;
    if ($phpbb->db_Connect($dbhost , $dbuser, $dbpasswd , $dbname))
    {
        $phpbb->db_Query($query);
        while ($row=$phpbb->db_Fetch())
        {
            $result .= $item_start.'<a href="'.$forum_url.'viewtopic.php?f='.$forum_id.'&t='.$row['topic_id'].'" title="'.$row['topic_title'].'">'.$row['topic_title'].'</a>'.$item_end;
        }
    }    
    echo $result;
}

function LoadLatestPosts($limit=5,$forum_url="http://winreview/forum/", $href_class="", $item_start="", $item_end="")
{
    global $dbhost,$dbuser,$dbpasswd,$dbname;
    #group_id in (1,2,3,7) guests, users,users_coppa, newbies    
    #gr.auth_role_id 16 - noaccess, 26 - view only
    $result = "";
    $phpbb=new db;
    if ($phpbb->db_Connect($dbhost , $dbuser, $dbpasswd , $dbname))
    {
        $query="select config_value from phpbb_config where config_name='posts_per_page'";
        $phpbb->db_Query($query);
        $row=$phpbb->db_Fetch();
        $posts_per_page = $row['config_value'];

        $query="select distinct topic_id,topic_title,topic_last_poster_name,topic_last_post_id,topic_replies_real from phpbb_topics t
            inner join phpbb_acl_groups gr on gr.forum_id=t.forum_id and group_id in (1,2,3,7)
            where t.forum_id not in (select forum_id from phpbb_acl_groups where gr.auth_role_id in (16,26))
             ORDER BY topic_last_post_id DESC LIMIT 0,".$limit;
        $phpbb->db_Query($query);
        while ($row=$phpbb->db_Fetch())
        {
                $start = intval( ceil( $row['topic_replies_real'] / $posts_per_page ) )*$posts_per_page;
                $start_url=$start>0 ? "start=".$start : "";
                $result .= $item_start.'<a href="'.$forum_url.'viewtopic.php?f='.$forum_id.'&t='.$row['topic_id'].'&'.$start_url.'#p'.$row['topic_last_post_id'].'" title="'.$row['topic_title'].'">'.$row['topic_title'].' ('.$row['topic_last_poster_name'].')</a>'.$item_end;
        }
    }    
    echo $result;
}

add_action('publish_post', 'wp2phpbb');
?>

Winreview.ru можно найти в Вконтакте, Facebook и Twitter. Присоединяйтесь!