Pivotで、FEEDの内容にまで置換ルールが適用される件

とりあえず、何がおかしいかと言うと、エントリの表示では置換されないのに、FEEDでは置換される。
どっちかに揃えてくれないと、結局内容が異なってしまうというワケで。

まぁ、エントリに合わせてくれればいいかな、と。
エントリ内で%author%を置き換えたい用事は現状ないし。

調べたところ、atom.xmlでは、summaryは置き換わらないがcontentは置き換わる。
rss.xmlでは、descriptionが置き換わる。

\pivot\modules\module_parser.php 内に該当箇所を発見。

    $from = array(
        "%title%",
        "%subtitle%",
        "%link%",
        "%description%",
        "%summary%",
        "%author%",
        "%guid%",
        "%date%",
        "%date_rfc%",
        "%category%",
        "%content%",
        "%tag%",
        "%lang%",
        "%vialink%",
        "%viatitle%"
    );

    $to = array(
        htmlspecialchars(strip_tags($title)),
        htmlspecialchars(strip_tags($subtitle)),
        $link,
        RelativeToAbsoluteURLS($description),
        RelativeToAbsoluteURLS($summary),
        $user,
        $uid."@".$weblog,
        $date,
        $date_rfc,
        implode(", ",$category),
        RelativeToAbsoluteURLS($content),
        $tag,
        $lang,
        $db->entry['vialink'],
        $viatitle
    );

    $rss_item= str_replace($from, $to, $rss_item);
    $atom_item= str_replace($from, $to, $atom_item);

str_replace関数に配列を渡して使うと、配列の先頭から順に処理が繰り返される。
つまり、

$rss_item = str_replace($from, $to, $rss_item);

for ($i = 0 ; $i < count($from) ; $i++) {
    $rss_item = str_replace($from[$i], $to[$i], $rss_item);
}

と等価。細かいフォローは抜きにして。

そんなワケで今回は、%summary%とかを置き換えたときに新たに置換対象に現れた%author%を、次の処理でさらに変換してしまったというコトですな。
一括で置換してくれればいいものを。

とりあえず、一括で置換する関数を作ってみた。

function str_replace_bundle($search, $replace, $subject) {
   
    if (!is_array($search) && !is_array($replace)) {
        return str_replace($search, $replace, $subject);
    }
    else if(!is_array($search)) {
        $search = array($search);
    }
    else if(!is_array($replace)) {
        $replace = array($replace);
    }
    $search = array_values($search);
    $replace = array_values($replace);
   
    $offset = 0;
    
    while (true) {
        $nearpos = strlen($subject);
        $nearkey = false;
        foreach ($search as $key => $value) {
            $pos = strpos($subject, $value, $offset);
            if ($pos === false) {
                continue;
            }
            if ($nearpos > $pos) {
                $nearpos = $pos;
                $nearkey = $key;
            }
        }
        if ($nearkey === false) {
            break;
        }
       
        $subject = substr($subject, 0, $nearpos)
            .$replace[$nearkey]
            .substr($subject, $nearpos + strlen($search[$nearkey]));
        $offset = $nearpos + strlen($replace[$nearkey]);
    }
   
    return $subject;
   
}

あんまり検証してない。とりあえずEUC-JPで日本語も問題ないっぽい。
Pivotの該当箇所もこれを使うように変更して修正完了。

ところでstr_replace()って割と「穴」なんじゃないですかね。
気をつけて使うようにしよう…


新しく会社作りました!

コメントをどうぞ