($autolink > 0) ページ名が「整数」のページを作成したときに、 recent プラグインなどにページ名が正しく反映されない

  • 元タイトル: bugtrack でページ名に数値を指定したときに、 recent プラグインでページ名が正しく表示されない
  • ページ: BugTrack2
  • 投稿者: 冒険者
  • 優先順位: 重要
  • 状態: 完了
  • カテゴリー: 本体バグ
  • 投稿日: 2006-05-16 (火) 20:23:36
  • バージョン: 1.4.7_rc1

修正

(1.4.7)

この件は BugTrack2/151 の対策中に発生した不具合の修正です。

  1. PHPの配列のキーに「整数として解釈できる文字列」を与えた場合、それは整数になります。これはPHP言語における配列の仕様のようです。
  2. PHP の標準関数 array_splice() に以下の様に配列を与える場合、そのキーに整数が含まれているとキーが保存されません。結果的に、連想配列の key=>value の関係を維持できない可能性が生じます。これはarray_splice() 関数の仕様のようです。
test.php
<?php
$a = array();
$a['dfsfsd'] = 1148083281;
$a['5344']   = 1148083151;
$a['88']     = 1148000281;
var_dump($a);

$a = array_splice($a, 0, 3);
var_dump($a);
?>
出力結果
array(3) {
  ["dfsfsd"]=>
  int(1148083281)
  [5344]=>           <= この時点で文字列ではない
  int(1148083151)
  [88]=>
  int(1148000281)
}
array(3) {
  ["dfsfsd"]=>
  int(1148083281)
  [0]=>              <= 整数の添え字がクリアされている
  int(1148083151)
  [1]=>              <=
  int(1148000281)
}
実際の修正内容
 	// Cut unused lines
-	$recent_pages = array_splice($recent_pages, 0, $maxshow + PKWK_MAXSHOW_ALLOWANCE);
+	// BugTrack2/179: array_splice() will break integer keys in hashtable
+	$count   = $maxshow + PKWK_MAXSHOW_ALLOWANCE;
+	$_recent = array();
+	foreach($recent_pages as $key=>$value) {
+		unset($recent_pages[$key]);
+		$_recent[$key] = $value;
+		if (--$count < 1) break;
+	}
+	$recent_pages = & $_recent;

メッセージ

bugtrack プラグインで、ページ名に数値 (9 とか 99 とか) を指定すると、 ページは正しく作成されるのですが、最新の ?? 件に 0 とか 1 とかの 存在しないページ名が表示されてしまいます。


  • お試しいただきありがとうございます :) -- henoheno 2006-05-16 (火) 21:07:07
    • 本件チェックします。 -- henoheno 2006-05-16 (火) 21:07:20
    • ページを新規に作成した場合、通常は絶対に「一つ」しかページが更新されませんが、bugtrackプラグインで「ページ名」を指定した場合、ページが「二つ」新規作成します。この挙動のせいでしょう。 -- henoheno 2006-05-16 (火) 21:14:21
    • なお、この操作をした場合「0」というページが(あってもなくても)recent.datに載ります。これがbugtrackプラグインによる二回目の更新行為ではないかと推測します。・・・と、以下で page_write() を二度読んでいる部分がそうです。 -- henoheno 2006-05-16 (火) 21:16:12
             // bugtrack.inc.php
             // ページ名が指定されているなら二度書き込む
             if ($pagename == '') {
                     page_write($page, $postdata);
             } else {
                     $pagename = get_fullname($pagename, $base);
                     if (is_page($pagename) || ! is_pagename($pagename)) {
                             $pagename = $page; // Set default
                     } else {
                             page_write($page, 'move to [[' . $pagename . ']]');
                     }
                     page_write($pagename, $postdata);
             }
  • この現象は $autlink が 0 の時 (今回のrecent.datの高速化が働く状況)は(※ほとんど)発生しませんね。 $autolink が有効の時に(※常に)発生します。 -- 2006-05-16 (火) 21:43:31
    • put_lastmodified() の中の array_splice() の中で、連想配列の key が失われている期待していない動作になっている模様です・・・ -- henoheno 2006-05-16 (火) 22:08:07
             // Cut unused lines
             $recent_pages = array_splice($recent_pages, 0, $maxshow + PKWK_MAXSHOW_ALLOWANCE);
  • この現象は、bugtrackに限ったことではなく、数字のみのページを新規作成した時であれば発生します。一般的な問題として、タイトルを(再)修正します。 -- henoheno 2006-05-16 (火) 22:33:59
  • array_splice() の前段階の部分における、配列の添え字の型の問題ではないかと思いますの可能性もあります。ページ名を「整数」にした場合、 $recent_pages の key は 文字列ではなく、整数になってしまいます。配列のkeyとして与えたものが整数に見える場合、PHPの配列は文字だろうが何だろうがそれを整数にしてしまいます。直前にkeyに対して(string)にキャストしたりstrvar()したり、$array["$key"]のように二重引用符で囲んでも効果はありません。以前も似たような話がありましたね・・・ -- henoheno 2006-05-16 (火) 23:46:17
           // Check ALL filetime
           $recent_pages = array();
           foreach($pages as $page)
                   if ($page != $whatsnew && ! check_non_list($page))
                           $recent_pages[$page] = get_filetime($page); // <= HERE
  • PHPの配列の仕様とarray_splice()の仕様の複合技の様ですね。上にサンプルを張っておきます。特に異常がなければ完了に。 -- henoheno 2006-05-20 (土) 00:04:58
  • cvs:lib/file.php (r1.69) を上書きして試してみました。
    「bugtrack」で作成した場合、「新規」で作成した場合、共に動作 OK です。
    ありがとうございました。 -- 冒険者 2006-05-22 (月) 09:35:58
    • cvs:lib/file.php (r1.70) も動作 OK です。 -- 冒険者 2006-05-22 (月) 14:14:29
  • こちらこそお知らせいただき(確認も含め)助かりました。有難うございました。 -- henoheno 2006-05-27 (土) 21:17:14

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2013-07-13 (土) 09:35:03
Site admin: PukiWiki Development Team

PukiWiki 1.5.2+ © 2001-2019 PukiWiki Development Team. Powered by PHP 5.6.40-0+deb8u7. HTML convert time: 0.286 sec.

OSDN