‘PHP’ カテゴリーのアーカイブ

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()って割と「穴」なんじゃないですかね。
気をつけて使うようにしよう…


i18n_ja_jp_hantozen

PHP3のi18n_ja_jp_hantozenはスペースの半角全角変換の[sS]対応してないのね…

/**
 * mb_convert_kana
 */
if( !function_exists('mb_convert_kana') ) {
 
 function mb_convert_kana( $str, $options = 'KV', $internal_enc = 'EUC-JP' ) {
  
  if (preg_match('/s/', $options)) {
   $str = str_replace(' ', ' ', $str);
  }
  else if (preg_match('/S/', $options)) {
   $str = str_replace(' ', ' ', $str);
  }
  
  return i18n_ja_jp_hantozen( $str, $options, $internal_enc );
  
 }
 
}

第3引数なんか使わねーよという勝手な理由により手抜き実装を施す。


GDでのフォント指定

GDでttc(TrueType Collection font file)ファイルを指定すると、普通に使えるけど、どのフォントが実際使われているか分からないし、設定もできない。
ので、一度バラすことにした。

breakttc.exeを使って分解して、できたttfファイルを指定してImageTTFTextを呼べばOK。

header ("Content-type: image/jpeg");

$im = imagecreatetruecolor (455, 75);
imageantialias ($im, true);
$black = ImageColorAllocate ($im, 0, 0, 0);
$white = ImageColorAllocate ($im, 255, 255, 255);

$font1 = "./DShirkg7.ttf";

$str = "ほげ\n";
$str = mb_convert_encoding( $str, 'UTF-8', 'EUC-JP' );

ImageTTFText ($im, 13.4, 0, 10, 29, $white, $font1, $str);

ImageJpeg ($im);
ImageDestroy ($im);

こんな感じで。
ImageTTFTextのサイズって普通に小数で指定できたのね。


PHP3の$HTTP_SERVER_VARS

何か定義されてなかった…orz

getallheaders()とgetenv()で対応。

で、Apacheのモジュール版じゃないとgetallheaders()が使えないので、自前で定義。

if ( !function_exists('getallheaders') ) {
   
    function getallheaders() {
       
        global $HTTP_SERVER_VARS;
       
        if (!empty($HTTP_SERVER_VARS) && is_array($HTTP_SERVER_VARS)) {
            reset( $HTTP_SERVER_VARS );
            while( $each_HTTP_SERVER_VARS = each($HTTP_SERVER_VARS) ) {
                $name = $each_HTTP_SERVER_VARS['key'];
                $value = $each_HTTP_SERVER_VARS['value'];
                if(substr($name, 0, 5) == 'HTTP_')
                    $headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value;
            }
        }
       
        return $headers;
       
    }
   
}


…Feedのdescriptionも置換されるょ…

('A`)<えー
ATOMのsummaryとRSSのdescriptionまでもが%author%を置換してしまう件…
Feed周りヤバいなぁ…

今日はこれ以上時間割けないので対応は次回。

それともまさか意図した動作なんでしょうか。


PivotのATOM FeedにnicknameじゃなくてログインIDの方が表示されてしまう件。

とりあえず%author%を追いかけてみる。

pivot/modules/module_parser.phpで置換をかけてるらしい。
…共通の置換エンジンがあるわけではないのか…

1849: "%author%",
(中略)
1869: $user,
(中略)
1882: $atom_item= str_replace($from, $to, $atom_item);

一応、対応タグは以下の通り。テンプレート内で、——で区切られた2番目の部分(item)に関してのみ。

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

で、辿っていくと$userは下記コードで定義されてる。

824: $entry = $db->read_entry($list_entry['code'], TRUE);
(中略)
846: add_rss($entry['code'], $entry['date'], $entry['title'], $entry['introduction'], $entry['body'], $entry['user'], $entry['category'] );

$entryの中見たらこんな感じ。

array(22) {
  ["code"]=>
  ["date"]=>
  ["introduction"]=>
  ["body"]=>
  ["category"]=>
    [0]=>
    [1]=>
  ["publish_date"]=>
  ["edit_date"]=>
  ["title"]=>
  ["subtitle"]=>
  ["user"]=>
  ["convert_lb"]=>
  ["status"]=>
  ["allow_comments"]=>
  ["keywords"]=>
  ["vialink"]=>
  ["viatitle"]=>
  ["commnames"]=>
  ["commcount"]=>
  ["commcount_str"]=>
  ["tracknames"]=>
  ["trackcount"]=>
  ["trackcount_str"]=>
}

…ニックネームないね。

$fromの定義の前に

1843: if (isset($Users[$user]['nick']) && $Users[$user]['nick'] != '') {
1844:     $user = $Users[$user]['nick'];
1845: }

こんなコード追加して解決。
あとglobalに$Users追加。

1778: global $db, $rss_items, $atom_items, $items_added, $Cfg, $Weblogs, $Current_weblog, $Allow_RSS, $Paths, $Users;

%author-nick%みたいなのを追加するというのでもいいかな。


Pivotの個別エントリが飛ばない件

ん?Pivotの.htaccessがおかしいような気が。
個別エントリが404になる。

RewriteRule ^entry/([0-9]*)/.*$

↓修正

RewriteRule ^entry/([0-9]*).*$

おk。


Image_Graphでpukiwiki用レーダーチャートプラグイン

Image_Graphでpukiwiki用レーダーチャートプラグインを作ったので、メモ。

まずPearのImage_Graphを入れる。

pear install –alldeps Image_Graph-alpha

とりあえずサンプルからコード持ってきていじる。

$Graph->add(
Image_Graph::vertical(
Image_Graph::factory('title', array('', 1)),
Image_Graph::vertical(
$Plotarea = Image_Graph::factory('Image_Graph_Plotarea_Radar'),
$Legend = Image_Graph::factory('legend'),
90
),
0
)
);

Image_Graph::verticalを使うと、縦のレイアウトが組める。第一引数と第二引数で表示する中身指定して、第三引数で第一エリアの表示領域をパーセンテージで指定する。入れ子にして自由にレイアウト組める。

とりあえず、今回タイトルもレジェンドもいらなかったので、さっくりシンプルに。

$Graph->add(
$Plotarea = Image_Graph::factory('Image_Graph_Plotarea_Radar')
);

これだけ。

あと、本来は自動で軸のスケールが決定されるけど、スケール指定したい場合はforceMaximumメソッドを使う。こんな感じ。

$AxisY =& $Plotarea->getAxis(IMAGE_GRAPH_AXIS_Y);
$AxisY->forceMaximum($axis_maximum);

ただし、スケールをはみ出す使い方はできない。値がクリップされるので、表示がおかしくなる。

あと日本語表示について。

$Font =& $Graph->addNew('font', './sazanami-gothic.ttf');

TTFのフォントをどこかに置いて、指定すればOK。ただし、ラベルはUTF-8で指定すること。

$DS1->addPoint(mb_convert_encoding('ほげ','UTF-8','EUC-JP'), 50);