ページ名を変更すると最新の~件のところに変更前のページ名が残る

  • ページ: BugTrack
  • 投稿者: cookie?
  • 優先順位: 低
  • 状態: 完了
  • カテゴリー: 本体バグ
  • 投稿日: 2006-09-11 (月) 00:46:40
  • バージョン: 1.4.7
  • リリース予定バージョン: 1.5.2

メッセージ

1.4.7 にしてからページ名の変更*1を行うと、最新の~件の欄に変更前のページ名と変更後のページ名の両方があらわれます。 変更前のページ名のほうは当然存在しないのでクリックすると新規ページの編集画面になってしまいます。

1.4.6 では発生していませんでした。 おそらく 1.4.7 で recent.dat まわりの変更をした影響だと思います。

関連


コメント

  • 観察とコメントをありがとうございます。これは恐らくその通りでしょう。今までrecent.datは毎回ディレクトリを総覧して生成されていましたから、べらぼうなコストを支払っていた代わりに、何も考える必要はありませんでした。1.4.7では不要な総覧を行わない様になりました。少しケアがいると思われます。 -- henoheno 2006-09-11 (月) 22:55:42
    • 対象としては recent.dat, およびRecentChanges、RecentDeleted辺りがあるでしょう。 -- henoheno 2006-09-11 (月) 22:56:16
  • official:質問箱3/592 に以下の指摘あり。 -- 2007-06-05 (火) 23:23:41
    • 「名前変更」時、変更が recent.dat に反映されていないように思われます。PHP DBG でソースアタッチしてみたところ、 rename.inc.php から file.php#lastmodified_add() 関数が最終的に呼ばれるかと思いますが、320行目の
      if (($update == '' || check_non_list($update)) && $remove == '')
          return; // No need
      check_non_list($update)) の $update が ':RenameLog' のため true が返り、以降の put_lastmodified() が実行されず結果 recent.dat に反映されないように思われます。pukiwikiにあまり詳しくないためこれが仕様なのか、また私の設定不足なのかわかりませんが、少なくとも1.4.5_1では recent.dat に反映されていました。宜しくお願いいたします。 -- skydog? 2007-01-28 (日) 16:36:03
    • lastmodified_add() は、$remove のページをリストから消して、$update のページをリストの一番上にもっていく、という2本立てでしかも、1ページ分ずつしかできない(この変数は配列にはできない)という仕様で、置換えには向いていません*2
      しかも、$update が$non_listの対象外でリストのページ数が足らない時か、AutoLinkを利用している時しかput_lastmodified() を呼ばないようになっています。
      対処療法で済ますのなら重い処理になりますが、
      	page_write(PLUGIN_RENAME_LOGPAGE, join('', $postdata));
      +	put_lastmodified();
      こうすれば全てのページ名を置換えてログをとった後に必ずput_lastmodified() を実行するという昔の動作にすることはできます。
      変更前のページ名をリストから消すだけでもいい*3のなら……、混乱してきたので、このページにではなく別ページにrenameプラグインの改良案として挙げるかもしれません 結局このページに挙げました。他の見直しもあわせると、長くなりそうですし。 -- 2007-09-17 (月) 11:58:00
  • decode() の多さに惑わされてました。自分にはどうにもできない部分なので案から切り捨てたたところ、それほど長くはならなさそうなのでここに。
    cvs:plugin/rename.inc.php (1.35)をベースに
     // Phase four: Rename them, Log them, Redirect
     function plugin_rename_phase4($pages, $files, $exists)
     {
     	global $now, $_rename_messages;
     
    -	if (plugin_rename_getvar('exist') == '')
    -		foreach ($exists as $key=>$arr)
    +	if (plugin_rename_getvar('exist') != '1') {
    +		foreach ($exists as $key=>$arr) {
     			unset($files[$key]);
    +			unset($pages[$key]);
    +		}
    +	}
     
     	set_time_limit(0);
     	foreach ($files as $page=>$arr) {
     		foreach ($arr as $old=>$new) {
     			if (isset($exists[$page][$old]) && $exists[$page][$old])
     				unlink($new);
     			rename($old, $new);
    -
    -			// Update link database (BugTrack/327) arino
    -			links_update($old);
    -			links_update($new);
     		}
     	}
     
     (中略)
     
     	if (! empty($exists)) {
    +		if (plugin_rename_getvar('exist') != '1') {
     			$postdata[] = "\n" . $_rename_messages['msg_result'] . "\n";
     			foreach ($exists as $page=>$arr) {
     				$postdata[] = '-' . decode($page) .
     					$_rename_messages['msg_arrow'] . decode($pages[$page]) . "\n";
    	  			foreach ($arr as $ofile=>$nfile)
     					$postdata[] = '--' . $ofile .
     						$_rename_messages['msg_arrow'] . $nfile . "\n";
    	  		}
     			$postdata[] = '----' . "\n";
    +		} else {
    +			(上書きしなかった時のメッセージ(検討課題))
    +		}
     	}
     
    -	foreach ($pages as $old=>$new)
    -		$postdata[] = '-' . decode($old) .
    -			$_rename_messages['msg_arrow'] . decode($new) . "\n";
    +	foreach ($pages as $old=>$new) {
    +		$old_page = decode($old);
    +		$new_page = decode($new)
    +
    +		$postdata[] = '-' . $old_page .
    +			$_rename_messages['msg_arrow'] . $new_page . "\n";
    +
    +		lastmodified_add('', $old_page);
    +
    +		links_update($old_page);
    +		links_update($new_page);
    +	}
     
     	// At this time, collision detection is not implemented
     
     	page_write(PLUGIN_RENAME_LOGPAGE, join('', $postdata));
     
     	$page = plugin_rename_getvar('page');
     	if ($page == '') $page = PLUGIN_RENAME_LOGPAGE;
     
     	// Redirection
     	pkwk_headers_sent();
     	header('Location: ' . get_script_uri() . '?' . rawurlencode($page));
     	exit;
     }
    まず最初のif文の条件変更ですが、「パスワード入力時点ではリネーム後のページがなかったが、置換え処理の直前には存在していた」という時は考慮しているのですが、
    「パスワード入力時点で判明していて、'そのページを処理しない'を選択して実行」した時に、無視して置換え処理をしているので、'そのファイルを上書きする'と選択した時以外は置換えしないようにしました。
    次にそのif文の中身ですが、置換えをキャンセルしたページまでログの一覧に表示されるのを防ぐためです。
    3番目にBugTrack/327で追加されたlinks_update() の処理位置についてですが、複数のファイルを置換えている途中で実行すると、あるファイルは置換え前に、またあるファイルは置換え後にリンクがあると誤判定してしまいそうなので、置換え処理が終わった後にもって来ました。
    最後にforeach ($pages as $old=>$new) の部分ですが、ページ名がdecode() された状態でないと困る処理を全部持ってきました(links_update() も含む)。置換え前のページ名をrecent.dat から消すという処理もここに持って来ています。ただ、AutoLink が有効になっているとput_lastmodified() を置換えページ数分実行してしまうので、改良の余地ありなんですけど。
    検討課題としてif (! empty($exists)) の中の処理で、「上書きした時としなかった時でメッセージを変える必要がある」ということでしょうか。置換え後のページ名を使うかどうかで$pages から置換えしなかったページ名をリストから消す処理をこの場所に持って来る必要があるかもしれません。
    一部非表示にしたのに、結局前よりも長くなったしまった。 -- 2007-09-17 (月) 14:40:24
    • 混乱が抜けきっていなかったせいだ~(とごまかしてみる)、ポカミスを修正しました。 -- 2007-09-18 (火) 22:10:27
  • 対応しました。ページ名変更時にrecent.datを削除します。BugTrack/2406の対応によりcache/recent.datは必要な時に自動で生成されるようになったので、recent.datを削除するだけで次回アクセス時にページ名の更新が反映されたRecentChangesが表示されます commit:683d0c1e61 -- umorigu 2017-06-20 (火) 01:29:28

関連?: $non_list の対象ページを削除した時に、必ずRecentDeleted が更新されたとして、recent.dat を更新している

  • RecentChanges のメモを非表示にしました。 -- 2007-09-17 (月) 14:40:24
  • もしかしたら、な原因の検証
    lib/file.php (1.80)
    function lastmodified_add($update = '', $remove = '')
    {
    (中略)
    	// Read (keep the order of the lines)
    	$recent_pages = $matches = array();
    	foreach(file_head($file, $maxshow + PKWK_MAXSHOW_ALLOWANCE, FALSE) as $line)
    		if (preg_match('/^([0-9]+)\t(.+)/', $line, $matches))
    			$recent_pages[$matches[2]] = $matches[1];
    
    	// Remove if it exists inside
    	if (isset($recent_pages[$update])) unset($recent_pages[$update]);
    	if (isset($recent_pages[$remove])) unset($recent_pages[$remove]);
    
    	// Add to the top: like array_unshift()
    	if ($update != '')
    		$recent_pages = array($update => get_filetime($update)) + $recent_pages;
    
    	// Check
    	$abort = count($recent_pages) < $maxshow;
    
    	if (! $abort) {
    		// Write
    		ftruncate($fp, 0);
    		rewind($fp);
    		foreach ($recent_pages as $_page=>$time)
    			fputs($fp, $time . "\t" . $_page . "\n");
    	}
    
    	flock($fp, LOCK_UN);
    	fclose($fp);
    
    	if ($abort) {
    		put_lastmodified(); // Try to (re)create ALL
    		return;
    	}
    'recent.dat' を修正するときに、更新や削除したページの過去データを削除するまではいいんですが、
    その後、更新したページのデータを何も確認せずに、1行目に追加しているようです。
    オートリンク機能を使っていたり、 データリストが$maxshow よりも少ない場合*4は、 作り直しているので問題にはならないですが、
    そうでなかった時、日時関係の確認やソートをせずに追加しているので、更新ページのほうが日付が古かった場合順番がおかしくなるみたいです。
    'recent.dat' を基にして'RecentChanges' を作るので、おかしなデータを引き継いで表示してしまうと。
    修正の必要がある場所が、ここだけならいいんですけど。 -- 2007-06-28 (木) 17:34:42
  • ひとまず、メモ。このサイトで$non_list の対象になるページ(spamの残骸ページ「:CategoryDev/Document/en.lng=」)を削除したところ、RecentDeleted がRecentChanges の一番上に来ました。RecentDeleted そのものは更新されていなさそう*7なので、どこかの処理順がまずいのかも。 -- 2007-09-16 (日) 02:13:52
    • やっと原因がわかったかも。
      lib/file.php (1.86)
      // Output to a file
      function file_write($dir, $page, $str, $notimestamp = FALSE)
      {
      (中略)
      	// ----
      	// Delete?
      
      	if ($dir == DATA_DIR && $str === '') {
      		// Page deletion
      		if (! $file_exists) return; // Ignore null posting for DATA_DIR
      
      		// Update RecentDeleted (Add the $page)
      		add_recent($page, $whatsdeleted, '', $maxshow_deleted);
      
      		// Remove the page
      		unlink($file);
      
      		// Update RecentDeleted, and remove the page from RecentChanges
      		lastmodified_add($whatsdeleted, $page);
      
      		// Clear is_page() cache
      		is_page($page, TRUE);
      
      		return;
      
      	} else if ($dir == DIFF_DIR && $str === " \n") {
      上でlastmodified_add() を呼ぶところは、どんな時でも$whatsdeleted を更新、$page の削除をした、として呼び出していますが、
      $page が$non_list の対象となった時、実際には$whatsdeleted は更新されていません(add_recent() が何もせずにreturn するため)。
      というわけで、if (check_non_list($page)) で分岐して、$non_list の対象となった時はlastmodified_add('', $page) と呼べばこの現象は解決すると思います。
      つまり、recent.dat の仕組みではなく、そこを呼び出すときのロジックがまずかったと。これ、かなり前からあるバグなんじゃないかと思ったり。 -- 2007-09-16 (日) 12:24:27


*1 renameプラグイン
*2 古いページがリストの一番上に行く可能性も
*3 両方残るから困るって頭にあったからこれでいいんじゃ…
*4 なんかこの処理の仕方も微妙、全ページ数が$maxshow よりも少ない時も該当する*5から
*5 でも$non_list 対象のページ除いて60未満なら、それほど負担にはならないのか*6な?
*6 ありえない例だけど、もしこの時に$non_list 対象のページが500 とかあったら結局は…
*7 RecentDeleted には「タイムスタンプを変更しない」オプションは無いはず

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

PukiWiki 1.5.1+ © 2001-2016 PukiWiki Development Team. Powered by PHP 5.6.30-0+deb8u1. HTML convert time: 0.412 sec.

OSDN