複数の PukiWiki サイトを一括管理する方法

複数の PukiWiki サイトを管理している/管理しようとしているあなたへ送る PukiWiki サイトを一括管理する方法のまとめです。

概要

以下、前提です。

  • 1つのウェブサーバ上に複数の PukiWiki サイトを設置・管理する場合を想定している。
  • PukiWiki システム本体を1つにし、複数のサイトで共有する。
    • PukiWiki のカスタマイズやバージョンアップ対応などは、この PukiWiki システム本体に対して集中的に行うことで対応できるようにする。
    • 全てのサイトで利用可能なデザイン(スキン・CSS)・プラグインを提供する形にする。
  • 各サイトは独自の設定・データ・デザイン・プラグインだけを管理する。
    • PukiWiki システム本体部分に持たせたデザイン・プラグインはもちろん使える。
    • 必要に応じて独自デザインの適用や独自プラグインの利用ができるようにする。

ざっくりと以下のようにファイルを配置して運用する形を想定します。

  • ServerRoot/PukiWiki(PukiWiki システム本体)
    • ja.lng.php
    • en.lng.php
    • rules.ini.php
    • image, lib, plugin, skin
  • ServerRoot/Site1(http://xxx.yyy.zzz/Site1/
    • index.php
    • attach, backup, cache, counter, diff, image, plugin, skin, trackback, wiki
  • ServerRoot/Site2(http://xxx.yyy.zzz/Site2/
    • index.php
    • attach, backup, cache, counter, diff, image, plugin, skin, trackback, wiki
  • ServerRoot/Site3(http://xxx.yyy.zzz/Site3/
    • index.php
    • attach, backup, cache, counter, diff, image, plugin, skin, trackback, wiki
  • ...

カスタマイズ概要

どこをどういう風にカスタマイズするか簡単に説明します。

  • 定数のカスタマイズ
    • PukiWiki のディレクトリ構成を決めている各種定数(XXX_DIR)を書き換えてシステム全体がアクセスする場所を制御する。
    • Web リソースアクセスがコントロールしやすいよう URI 定数群を導入する。
    • ディレクトリ定数と URI 定数を PukiWiki 本体とサイト独自の2系統用意し、状況に応じて使い分けができるようにする。
  • exist_plugin メソッドを書き換えて、PukiWiki 本体とサイト独自の両方のプラグインを認識してくれるようにする。

カスタマイズ内容

具体的なカスタマイズ箇所を見ながら説明します。

まずはディレクトリ構成に関する定数は index.php と pukiwiki.ini.php に定義されています。

  • index.php
// Directory definition
// (Ended with a slash like '../path/to/pkwk/', or '')
define('DATA_HOME',	'');
define('LIB_DIR',	'lib/');
  • pukiwiki.ini.php
/////////////////////////////////////////////////
// Directory settings I (ended with '/', permission '777')

// You may hide these directories (from web browsers)
// by setting DATA_HOME at index.php.

define('DATA_DIR',      DATA_HOME . 'wiki/'     ); // Latest wiki texts
define('DIFF_DIR',      DATA_HOME . 'diff/'     ); // Latest diffs
define('BACKUP_DIR',    DATA_HOME . 'backup/'   ); // Backups
define('CACHE_DIR',     DATA_HOME . 'cache/'    ); // Some sort of caches
define('UPLOAD_DIR',    DATA_HOME . 'attach/'   ); // Attached files and logs
define('COUNTER_DIR',   DATA_HOME . 'counter/'  ); // Counter plugin's counts
define('TRACKBACK_DIR', DATA_HOME . 'trackback/'); // TrackBack logs
define('PLUGIN_DIR',    DATA_HOME . 'plugin/'   ); // Plugin directory

/////////////////////////////////////////////////
// Directory settings II (ended with '/')

// Skins / Stylesheets
define('SKIN_DIR', 'skin/');
// Skin files (SKIN_DIR/*.skin.php) are needed at
// ./DATAHOME/SKIN_DIR from index.php, but
// CSSs(*.css) and JavaScripts(*.js) are needed at
// ./SKIN_DIR from index.php.

// Static image files
define('IMAGE_DIR', 'image/');
// Keep this directory shown via web browsers like
// ./IMAGE_DIR from index.php.

ここを以下のように書き換えます。

  • index.php
    • PKWK_HOME は PukiWiki 本体の場所を表す。
    • DATA_HOME は サイト独自の場所を表す。
    • URI は HTTP でアクセスする場合に使用する URL の値を表す。
    • PKWK_URI が PukiWiki 本体の場所を表す。すなわち共有リソースの場所である。
    • ROOT_URI はサイト独自の場所を表す。すなわち独自リソースの場所である。
define('PKWK_HOME', '../PukiWiki/');
define('DATA_HOME', '');
define('LIB_DIR', PKWK_HOME . 'lib/');

// Base URL
define('ROOT_URI', preg_replace('#[^/]*$#', '', $_SERVER['SCRIPT_NAME']));
define('PKWK_URI', ROOT_URI . PKWK_HOME);
  • pukiwiki.ini.php
    • 先頭 C_ なしのディレクトリや URI が PukiWiki 本体の場所である。
    • 先頭 C_ 付きのディレクトリや URI がサイト独自の定義である。
    • ただし、data, diff, backup ... などはサイト独自のものしかないので、そのままである。

サイト独自のものに先頭 C_ 付きの新しい名前をつけるのは、PukiWiki 本体のリソースを標準として使うためです。

/////////////////////////////////////////////////
// Directory/URI (ended with '/')

define('DATA_DIR',      DATA_HOME . 'data/wiki/'     ); // Latest wiki texts
define('DIFF_DIR',      DATA_HOME . 'data/diff/'     ); // Latest diffs
define('BACKUP_DIR',    DATA_HOME . 'data/backup/'   ); // Backups
define('CACHE_DIR',     DATA_HOME . 'data/cache/'    ); // Some sort of caches
define('UPLOAD_DIR',    DATA_HOME . 'data/attach/'   ); // Attached files and logs
define('COUNTER_DIR',   DATA_HOME . 'data/counter/'  ); // Counter plugin's counts
define('TRACKBACK_DIR', DATA_HOME . 'data/trackback/'); // TrackBack logs
define('PLUGIN_DIR',    PKWK_HOME . 'plugin/'        ); // Plugin directory
define('C_PLUGIN_DIR',  DATA_HOME . 'plugin/'        ); // Plugin directory

define('SKIN_DIR',      PKWK_HOME . 'skin/'          );
define('C_SKIN_DIR',    DATA_HOME . 'skin/'          );
define('CSS_DIR',       PKWK_HOME . 'css/'           ); // CSS directory
define('C_CSS_DIR',     DATA_HOME . 'css/'           ); // CSS directory
define('IMAGE_DIR',     PKWK_HOME . 'image/'         );
define('C_IMAGE_DIR',   DATA_HOME . 'image/'         );

define('CACHE_URI',     PKWK_URI . 'cache/'          );
define('SKIN_URI',      PKWK_URI . 'skin/'           );
define('C_SKIN_URI',    ROOT_URI . 'skin/'           );
define('IMAGE_URI',     PKWK_URI . 'image/'          );
define('C_IMAGE_URI',   ROOT_URI . 'image/'          );
define('CSS_URI',       PKWK_URI . 'css/'            );
define('C_CSS_URI',     ROOT_URI . 'css/'            );
define('JS_URI',        PKWK_URI . 'js/'             );
define('C_JS_URI',      ROOT_URI . 'js/'             );

定数を定義したら使っている箇所を必要に応じて書き換えます。

まず最初に default.ini.php の先頭です。

if (defined('TDIARY_THEME')) {
	define('SKIN_FILE', SKIN_DIR . 'tdiary.skin.php');
} else {
	define('SKIN_FILE', SKIN_DIR . 'pukiwiki.skin.php');
}

SKIN_DIR は PukiWiki システム本体のスキンを使うことを意味します。 もしもサイト独自のスキンを使う場合は SKIN_DIR を C_SKIN_DIR に書き換えます。

スキン全般の Web リソースアクセス個所の書き換えも必要です。以下事例です。

  • skin/pukiwiki.skin.php

書き換え前

 <link rel="stylesheet" type="text/css" media="screen" href="skin/pukiwiki.css.php?charset=<?php echo $css_charset ?>" charset="<?php echo $css_charset ?>" />

書き換え後

 <link rel="stylesheet" type="text/css" media="screen" href="<?php echo SKIN_URI ?>/pukiwiki.css.php?charset=<?php echo $css_charset ?>" charset="<?php echo $css_charset ?>" />

などです。

以上の書き換え例は PukiWiki システム本体の CSS スキンを使う場合の例ですが、 もしもサイト独自の CSS を使う場合は SKIN_URI を C_SKIN_URI に書き換えます。

ファイル構成としては PukiWiki システム本体に標準スキンを置いておき、サイト独自のスキンは必要に応じて設置します。不要なら削除してかまいません。

画像や CSS や JavaScript などの各種リソース群もスキンと同様の考え方をします。 標準のものを使うか独自のものを使うかはアクセスする場所で使用する定数の違いによって表現します。

最後にプラグインに関する調整を行います。

このままではサイト独自のプラグイン定義ができません。標準の PukiWiki はプラグインが単一のディレクトリに入っていることを想定しているからです。

一カ所書き換えれば対応できます。それが lib/plugin.php の exist_plugin 関数です。

// Check plugin '$name' is here
function exist_plugin($name)
{
	global $vars;
	static $exist = array(), $count = array();

	$name = strtolower($name);
	if(isset($exist[$name])) {
		if (++$count[$name] > PKWK_PLUGIN_CALL_TIME_LIMIT)
			die('Alert: plugin "' . htmlsc($name) .
			'" was called over ' . PKWK_PLUGIN_CALL_TIME_LIMIT .
			' times. SPAM or someting?<br />' . "\n" .
			'<a href="' . get_script_uri() . '?cmd=edit&amp;page='.
			rawurlencode($vars['page']) . '">Try to edit this page</a><br />' . "\n" .
			'<a href="' . get_script_uri() . '">Return to frontpage</a>');
		return $exist[$name];
	}

	// 書き換え開始(C_PLUGIN_DIR を先に見て、なければ PLUGIN_DIR を見る)
	if (preg_match('/^\w{1,64}$/', $name)) {
		if (file_exists(C_PLUGIN_DIR . $name . '.inc.php')) {
			$exist[$name] = TRUE;
			$count[$name] = 1;
			require_once(C_PLUGIN_DIR . $name . '.inc.php');
			return TRUE;
		}

		if (file_exists(PLUGIN_DIR . $name . '.inc.php')) {
			$exist[$name] = TRUE;
			$count[$name] = 1;
			require_once(PLUGIN_DIR . $name . '.inc.php');
			return TRUE;
		}
	}

	$exist[$name] = FALSE;
	$count[$name] = 1;
	return FALSE;
	// 書き換え終了
}

これでサイト独自のプラグイン導入ができるようになります。

スキン等で直接プラグインを呼び出したい場合は、以下の書き方をすれば OK です。

<?php if (exist_plugin("pluginname")) { echo plugin_example_inline(); } ?>

このページを書くにいたった経緯

自分はホームページ全般を PukiWiki で作成しています。

Wiki でページが掛けるのはとても楽だし、特別なページが必要であればプラグイン製作で大抵のことが実現できます。

アクセスさえできればどこからでも編集できる気軽さも嬉しいです。パソコンからでもスマホからでも編集できます。

デザインを変えたいと思えばスキンを変えればそれだけでサイト全体のデザインが一括で変わります。

そんなこともあってたくさんの PukiWiki を設置していました。たくさん設置していたのはテーマ毎に分けて設置していたからです。

まずまず満足してましたが PukiWiki の開発が止まっていることだけが気がかりでした。他の Wiki に乗り換えようかと思う日々が続きました。

しかし、その不安を打ち破る PukiWiki 1.5.0 の公開に心躍りました!新しいのに乗り換えよう!すぐにそう思ったけど今日までできずにいました。

たくさんの PukiWiki が立っていたからです。メンテナンスの問題がそこにあったのです。

この解決策により今後のバージョンアップ対応時の不安も払拭されました。安心してバージョンアップできるようになりました。

ヒント:複数ウェブサーバで PukiWiki を運営しているとしたらどうすればいいか。

複数のウェブサーバで PukiWiki を使っている人がいるでしょう。

自分は実際にやってないのでなんともいえないですがヒントだけ書いておきます。

まず、全てのウェブサーバでここで書いている方式をとりましょう。

そして PukiWiki システム本体部分をバージョン管理システムに載せて同期が取れるようにしましょう。

PukiWiki システム本体とサイト独自の部分が分離されるので、このようなことがしやすくなるはずです。