Pukiwiki 見出しタイトル化

2017/03/10Programming::PukiWiki

Pukiwiki改造: 見出しタイトル化

最初に出現したレベル1見出しをページタイトル(titleとh1)に反映する改造です。

改造前のconvert_htmlにbodycache用の記述も含まれているので、使っていない場合は無視してください。

  • lib/convert_html.php
    • function convert_html
      • 変更前
        function convert_html($lines)
        {
        	global $vars, $digest;
        	global $bodycache_status;
        	static $contents_id = 0;
        
        	if ( $bodycache_status === 'cached' ) {
        		$contents_id += 90 ;
        	}
        
        	// Set digest
        	$digest = md5(join('', get_source($vars['page'])));
        
        	if (! is_array($lines)) $lines = explode("\n", $lines);
        
        	$body = new Body(++$contents_id);
        	$body->parse($lines);
        
        	return $body->toString();
        }
        
      • 変更後: 「global $title, $page;」と「if ( isset( $body->title ) )~」を追記。
        function convert_html($lines)
        {
        	global $vars, $digest;
        	global $title, $page;
        	global $bodycache_status;
        	static $contents_id = 0;
        	
        	if ( $bodycache_status === 'cached' ) {
        		$contents_id += 90 ;
        	}
        
        	// Set digest
        	$digest = md5(join('', get_source($vars['page'])));
        
        	if (! is_array($lines)) $lines = explode("\n", $lines);
        
        	$body = new Body(++$contents_id);
        	$body->parse($lines);
        	
        	if ( isset( $body->title ) ){
        		$page = $title = htmlsc(trim($body->title));
        	}
        
        	return $body->toString();
        }
        
    • Heading::function Heading
      • 変更前
        	function Heading(& $root, $text)
        	{
        		parent::Element();
        
        		$this->level = min(3, strspn($text, '*'));
        		list($text, $this->msg_top, $this->id) = $root->getAnchor($text, $this->level);
        		$this->insert(Factory_Inline($text));
        		$this->level++; // h2,h3,h4
        	}
        
      • 変更後
        	function Heading(& $root, $text)
        	{
        		parent::Element();
        
        		$this->level = min(3, strspn($text, '*'));
        
        		if( $this->level === 1 && !isset( $root->title ) && $root->id === 1 ){
        			$root->title = preg_replace('|\s*\[#.*|', '', $text);
        			$root->title = preg_replace('|^\*\s*|', '', $root->title);
        			$root->title = preg_replace('|\[\[([^>\]]+)(>[^>\]]+)?\]\]|', '$1', $root->title);
        		}
        
        		list($text, $this->msg_top, $this->id) = $root->getAnchor($text, $this->level);
        		$this->insert(Factory_Inline($text));
        		$this->level++; // h2,h3,h4
        	}
        

2016/09/11(日)RecentChangesページを考慮したブラウザキャッシュ制御

PukiWiki: RecentChangesページを考慮したブラウザキャッシュ制御

PukiWiki If-Modified-Since(条件付きリクエスト)対応のコメントでやりとりしていた、RecentChangesページを考慮したブラウザキャッシュ制御の機能をbodycache改良版に追加しました。

PukiWiki bodycache改良版のページで公開しています。なお、追加機能を使うには設定が必要です。*1

RecentChangesを考慮したページ更新日時

基本的な方針は、「Wikiページキャッシュ更新日時とRecentChanges更新日時のうち新しい方」をページの更新日時と見なすというものです。

以下の関数がこの新しい方の更新日時を返す関数です。$bodycache_lastmod_whatsnewはpukiwiki.ini.php内の設定で、$bodycache_lastmod_whatsnewがtrueの時のみこの機能は動作します。

  • bodycache.php
    // Get last-modified time for client side cache control
    function get_lastmodtime($page)
    {
    	global $bodycache_lastmod_whatsnew;
    	global $whatsnew;
    	static $lastmodtime = null ;
    	if ($lastmodtime !== null) {
    		return $lastmodtime ;
    	}
    
    	$cachetime = get_cachetime($page);
    	if ( $cachetime != 0 && $bodycache_lastmod_whatsnew ) {
    		$whatsnewtime = get_filetime($whatsnew);
    		$lastmodtime = ( $cachetime >= $whatsnewtime ) ? $cachetime : $whatsnewtime;
    	} else {
    		$lastmodtime =  $cachetime;
    	}
    
    	return $lastmodtime;
    }
    

この関数が返す日時を、ブラウザに返却するLast-Modifiedや、If-modified-sinceの比較に用いることで、RecentChanges更新時にはブラウザキャッシュも更新される動作になります。

追記

get_lastmodtimeは複数回呼ばれるので、処理量を減らすために1回目に呼ばれたときの結果を$lastmodtimeに残して2回目以降は$lastmodtimeを返すだけにしているのですが、今の書き方では引数の$pageを変更して呼ばれると正しく動作しなくなってしまいます。

今のコードでは、$pageを変更してget_lastmodtimeを呼ぶことはないので問題は起こりませんが、get_lastmodtimeの引数を変えてはいけないという制約ができてしまっているのであまり良くないですね。(うっかり忘れて将来事故を起こしそう^^;)そのうち修正するかもしれません。

*1 : 機能が不要な場合に負荷が増えないように。

その他のbodycache改良版の更新

更新のついでに、bodycache.php内の不要な記述の削除とコードインデントのタブへの統一*2も実施しました。

また、bodycache.php内にあった設定用の変数$bodycache_del_depthをpukiwiki.ini.phpに移動しました。

*2 : PukiWikiのコードが基本的にタブだったので。

PukiWiki 多重includeの深さ制限

2016/06/25Programming::PukiWiki

PukiWiki 多重includeの深さ制限

多重include(includeの中でincludeを使う)の深さを制限できる改造版includeを作成しました。

制限を超えると、エラーメッセージ

#include(): Limit exceeded (recursive): ページ名

が表示されます。

使い方

  1. 設定
    • 添付のinclude.inc.php内のPLUGIN_INCLUDE_MAX_DEPTHを、必要に応じて変更します。
      // Max depth of recursive include
      define('PLUGIN_INCLUDE_MAX_DEPTH', 2);
      
      • 1で多重include禁止、2で二重まで許可。以降数字を増やすごとに許可される深さが増えます。
      • 0は無制限(もとのincludeと同じ)。
      • PukiWiki bodycache改良版のデフォルト設定は、二重includeまで対応しています。ただし、pcommentも含めて二重なので、pcommentで深さを1つ消費すると考えるとPLUGIN_INCLUDE_MAX_DEPTHの設定は1にするのが良いでしょう。
  2. 設置
    • include.inc.phpを、PukiWikiに元からあるinclude.inc.phpと置き換えます。

参考:改造内容

  • 上の方に設定値を追加
    // Max depth of recursive include
    define('PLUGIN_INCLUDE_MAX_DEPTH', 2);
    // e.g.
    //   PLUGIN_INCLUDE_MAX_DEPTH=0: no prohibition
    //   PLUGIN_INCLUDE_MAX_DEPTH=1: prohibit recursive include
    
  • function plugin_include_convertの冒頭に変数$depthを追加。
    function plugin_include_convert()
    {
    	global $script, $vars, $get, $post, $menubar, $_msg_include_restrict;
    	static $included = array();
    	static $count = 1;
    	static $depth = 1; //追加
    
  • PLUGIN_INCLUDE_MAX判定の直後に、PLUGIN_INCLUDE_MAX_DEPTHの判定を追加。*1
    	if (isset($included[$page])) {
    		return '#include(): Included already: ' . $link . '<br />' . "\n";
    	} if (! is_page($page)) {
    		return '#include(): No such page: ' . $s_page . '<br />' . "\n";
    	} if ($count > PLUGIN_INCLUDE_MAX) {
    		return '#include(): Limit exceeded: ' . $link . '<br />' . "\n";
    	} if ($depth > PLUGIN_INCLUDE_MAX_DEPTH && PLUGIN_INCLUDE_MAX_DEPTH > 0) { //追加
    		return '#include(): Limit exceeded (recursive): ' . $link . '<br />' . "\n"; //追加
    	} else {
    		++$count;
    	}
    
  • convert_htmlの前後に、$depthのインクリメントとデクリメントを追加。
    	if (check_readable($page, false, false)) {
    		++$depth; //追加
    		$body = convert_html(get_source($page));
    		--$depth; //追加
    	} else {
    		$body = str_replace('$1', $page, $_msg_include_restrict);
    	}
    

関連記事

*1 : if/elseの書き方が気持ち悪いのですが、元の書き方に倣いました。ifの中が全部returnなので、動作上は問題ないはず。

添付

ライセンスはGPLv2 or laterです。(PukiWikiと同じ。)

PukiWiki bodycache改良版