XSNSモジュールのd3pipesジョイントで新着コメント本文を取得したい anchor.png

XSNSモジュール-1.1.1を使用させていただいています。
本格的に使い始めたところで、ちょっと問題に直面しまして解決させたので、役に立つ場面もあるかと思い、記事にしておきます。

概要 anchor.png

  • XSNSで新着トピブロックを使ったとき、ブロックに表示される新着リンクをクリックしても、トピックの頭の説明にジャンプします。mixiでもトピの頭に飛ぶので同様の仕様と言えますが、これを最新記事にジャンプさせたいと思いました。
  • XSNSのd3pipesブロックジョイントクラス「D3pipおesBlockXsnstopiclist.class.php」で取得するトピックの本文が、最新のコメントではなく、毎回トピ説明が同じように繰り返されます。 ここはやはり、「新着コメント」のほうの本文を通知してほしいものです。

ということで、原因を探してましたが、どうやら「(trust)/modules/blocks/block_functions.php」「function b_xsns_recent_topic_show」の中でDBから取得するSQLに問題がありそう。。 :roll:

問題の箇所 anchor.png

 以下の説明は私も勉強しながら知った身なので言うことが間違っているかもしれません。
 下のSQL文で、GROUP BY tidでトピックIDでグループ化して抽出、MAX(tc.number)、MAX(tc.r_datetime)で各最大値を取得する、までは良いのですが、そこに様々な他のフィールドを検索取得するような指定を並べてます。
 この方法は、結果を保証されない方式であるとの情報もありますし、最新コメントのbodyが得られそうで実際には得られていません。

「(trust)/modules/blocks/block_functions.php」の25行目付近

25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
    // topic search
    $sql = "SELECT ".
            "c.c_commu_id AS cid,".
            "c.name AS cname,".
            "c.uid_admin AS cadmin,".
            "c.uid_sub_admin AS csubadmin,".
            "c.public_flag AS cflag,".
            "t.c_commu_topic_id AS tid,".
            "t.name AS tname,".
            "tc.body AS tcbody,".
            "tc.uid AS tcuid,".
            "MAX(tc.number) AS comment_count,".
            "MAX(tc.r_datetime) AS max_r_datetime".
            " FROM (". $db->prefix($mydirname.'_c_commu'). " c".
            " INNER JOIN ". $db->prefix($mydirname.'_c_commu_topic_comment'). " tc".
            " USING(c_commu_id))".
            " INNER JOIN ". $db->prefix($mydirname.'_c_commu_topic'). " t".
            " USING(c_commu_topic_id)".
            " GROUP BY tid".
            " ORDER BY max_r_datetime DESC";

改善案 anchor.png

 そこで、自分なりに見やすいクエリ2つに分割しました。
 また、飛び先のURLのトピ内コメントアンカー番号にジャンプするようにしてあります。 :-)
 (090525修正:リンク先にページ開始番号が抜けていたので追加しました。)

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
function b_xsns_recent_topic_show($options)
{
    global $xoopsUser, $xoopsUserIsAdmin;
    
    require_once dirname(dirname(__FILE__)).'/include/common_functions.php';
    
    $db =& Database::getInstance();
    $myts =& MyTextSanitizer::getInstance();
    
    $mydirname = empty($options[0]) ? 'xsns' : $options[0];
    $item_limit = empty($options[1]) ? 5 : intval($options[1]);
    
    if( preg_match( '/[^0-9a-zA-Z_-]/' , $mydirname ) ) die( 'Invalid dirname' ) ;
    
    $constpref = '_MB_'.strtoupper($mydirname);
    
    $block = array();
    $perm_arr = array();
    
    $own_uid = is_object($xoopsUser) ? $xoopsUser->getVar('uid') : -1;
    
    // naao from
    //各トピの最新コメントIDを取得
    $sql = "SELECT c_commu_topic_id AS tid, MAX(c_commu_topic_comment_id) AS com_id FROM ". $db->prefix($mydirname.'_c_commu_topic_comment')." GROUP BY tid;";
 
    $result = $db->query($sql);
    if(!$result || $db->getRowsNum($result) < 1){
        return array();
    }
    
    while ( $dbdat = $db->fetchArray($result)){
        $com_num[] = intval($dbdat['com_id']);
    }
 
      $whr_num = "tc.c_commu_topic_comment_id IN (" .implode( "," , $com_num ). ") ";
 
    // topic search
    $sql = "SELECT ".
            "c.c_commu_id AS cid,".
            "c.name AS cname,".
            "c.uid_admin AS cadmin,".
            "c.uid_sub_admin AS csubadmin,".
            "c.public_flag AS cflag,".
            "t.c_commu_topic_id AS tid,".
            "t.name AS tname,".
            "tc.body AS tcbody,".
            "tc.uid AS tcuid,".
            "tc.number AS comment_count,".
            "tc.r_datetime AS r_datetime,".
            "tc.c_commu_topic_comment_id ".
            " FROM (". $db->prefix($mydirname.'_c_commu'). " c".
            " INNER JOIN ". $db->prefix($mydirname.'_c_commu_topic_comment'). " tc".
            " USING(c_commu_id))".
            " INNER JOIN ". $db->prefix($mydirname.'_c_commu_topic'). " t".
            " USING(c_commu_topic_id)".
            " WHERE ".$whr_num.
            " ORDER BY r_datetime DESC";
    // naao to
    
    $rs = $db->query($sql);
    if(!$rs || $db->getRowsNum($rs) < 1){
        return array();
    }
    
    $today = date('Y-m-d');
    $item_count = 0;
    require_once dirname(dirname(__FILE__)).'/userlib/utils.php';
    
    while($row = $db->fetchArray($rs)) {
        
        if($item_limit <= $item_count){
            break;
        }
        
        // check community permission
        if($row['cflag']==3 && !$xoopsUserIsAdmin && $row['cadmin']!=$own_uid && $row['csubadmin']!=$own_uid){
            if($own_uid < 0){
                continue;
            }
            $cid = intval($row['cid']);
            if(!isset($perm_arr[$cid])){
                $perm_arr[$cid] = xsns_is_community_member($mydirname, $cid, $own_uid);
            }
            if(!$perm_arr[$cid]){
                continue;
            }
        }
        
        //$date_arr = explode(' ', XsnsUtils::getUserDatetime($row['max_r_datetime']), 2);
        $date_arr = explode(' ', XsnsUtils::getUserDatetime($row['r_datetime']), 2);    //naao
        if(!is_array($date_arr)){
            continue;
        }
        if($today==$date_arr[0]){
            $r_time_arr = explode(':', $date_arr[1], 3);
            if(!is_array($r_time_arr)){
                continue;
            }
            $r_time = $r_time_arr[0].':'.$r_time_arr[1];
        }
        else{
            $r_time_arr = explode('-', $date_arr[0], 3);
            if(!is_array($r_time_arr)){
                continue;
            }
            $r_time = $r_time_arr[1]. constant($constpref.'_MONTH'). $r_time_arr[2]. constant($constpref.'_DAY');
        }
        
            $comment_index = intval(intval($row['comment_count'])/20)*20;    //naao
            
        $block['topic_list'][] = array(
            'link' => XOOPS_URL.'/modules/'.$mydirname.'/?p=topic&tid='.intval($row['tid']).'&s='.$comment_index.'#'.intval($row['comment_count']),    //naao
            'title' => $myts->htmlSpecialChars($row['tname']),
            'body' => $myts->htmlSpecialChars($row['tcbody']),
            'comment_count' => intval($row['comment_count']),
            'datetime' => $r_time,
        //    'time' => XsnsUtils::getUserTimestamp($row['max_r_datetime']),    //naao
            'time' => XsnsUtils::getUserTimestamp($row['r_datetime']),    //naao
            'uid' => intval($row['tcuid']),
            'community' => array(
                'link' => XOOPS_URL.'/modules/'.$mydirname.'/?cid='.intval($row['cid']),
                'title' => $myts->htmlSpecialChars($row['cname']),
            ),
        );
        
        $item_count++;
    }
    
    if(empty($options['disable_renderer'])){
        require_once XOOPS_ROOT_PATH.'/class/template.php' ;
        $tpl =& new XoopsTpl();
        $tpl->assign('block', $block);
        $ret['content'] = $tpl->fetch('db:'.$mydirname.'_block_recent_topic.html');
        return $ret;
    }
    else{
        return $block;
    }
}

その他 anchor.png

 コメントを編集したときに、トピックの更新日時も更新されてしまいます。 これは考え方の違いだと思うのですが、ユーザーがタイプミスを修正したり追記をしたりした時でも更新と判断されてしまいますので、私は「edit_execAction.php」の当該箇所をコメントアウトしました。 103行目付近と、121行目付近の

//'r_datetime' => $r_datetime, // naao 編集時に、トピ日時を更新しない

ただ、これは現状の仕様のほうが適切なのかもしれず、何とも悩ましいところですね。


実体ページ:inc/xsns_d3pipes
関連ページ: