起動時に実行されるのはlib/init.phpとlib/pukiwiki.phpぐらい。
他はデータ(URLクエリーに含まれる'cmd'と'plugin'、それとページに書かれたWikiText)次第。
→機能のほとんどがElement系クラス経由で呼び出されている。プラグインも。


記法を探す→Element系オブジェクトに変換→それぞれのオブジェクトでWikiの機能を実現。
→拡張点はElement系クラスを追加すること。


インライン要素を含むことができるElement系クラスでInlineが生成される。Inline→make_link()→インラインプラグイン
→Element系クラスの構造に制限無し。ルールはBodyでElement系クラスを生成するということくらい。後はElement系クラス各々の自由。


ブロックプラグイン呼び出しができるのはElement系クラスのDivだけ。

呼び出し関係(抄) Edit

index.php

	lib/pukiwiki.php

		lib/mbstring.php
			 * mbstring extension がサーバー側に存在しない時の代替関数
			if (is_readable(JCODE_FILE)) {
				require_once(JCODE_FILE);
			}

		lib/init.php
			// Init PukiWiki here

			if (! file_exists(INI_FILE) || ! is_readable(INI_FILE)) {
			} else {
				require(INI_FILE);
			}
			if ($die) lib/func.php/die_message(nl2br("\n\n" . $die));

			lib/mbstring.php/mb_language(MB_LANGUAGE);
			lib/mbstring.php/mb_internal_encoding(SOURCE_ENCODING);
			lib/mbstring.php/mb_http_output('pass');
			lib/mbstring.php/mb_detect_order('auto');
			foreach (array('LANG_FILE_HINT', 'LANG_FILE') as $langfile) {
				if (! file_exists(constant($langfile)) || ! is_readable(constant($langfile))) {
				} else {
					require_once(constant($langfile));
				}
			}

			/////////////////////////////////////////////////
			// INI_FILE: Init $script

			if (isset($script)) {
				lib/func.php/get_script_uri($script); // Init manually
			} else {
				lib/func.php/get_script_uri(); // Init automatically
			}

			// Profile-related init and setting
			if (! file_exists(UA_INI_FILE) || ! is_readable(UA_INI_FILE)) {
				lib/func.php/die_message('UA_INI_FILE for "' . UA_PROFILE . '" not found.');
			} else {
				require(UA_INI_FILE); // Also manually
			}

			/////////////////////////////////////////////////
			// 外部からくる変数のチェック

			// Remove null character etc.
			lib/func.php/input_filter($_GET);
			lib/func.php/input_filter($_POST);
			lib/func.php/input_filter($_COOKIE);

			// 文字コード変換 ($_POST)
			if (isset($_POST['encode_hint']) && $_POST['encode_hint'] != '') {
				lib/mbstring.php/mb_detect_encoding($_POST['encode_hint']);
				lib/mbstring.php/mb_convert_variables(SOURCE_ENCODING, $encode, $_POST);
			} else if (isset($_POST['charset']) && $_POST['charset'] != '') {
				if (lib/mbstring.php/mb_convert_variables(SOURCE_ENCODING,
					lib/mbstring.php/mb_convert_variables(SOURCE_ENCODING, 'auto', $_POST);
				}
			} else if (! empty($_POST)) {
				lib/mbstring.php/mb_convert_variables(SOURCE_ENCODING, 'auto', $_POST);
			}

			// 文字コード変換 ($_GET)
			if (isset($_GET['encode_hint']) && $_GET['encode_hint'] != '')
			{
				$encode = lib/mbstring.php/mb_detect_encoding($_GET['encode_hint']);
				lib/mbstring.php/mb_convert_variables(SOURCE_ENCODING, $encode, $_GET);
			}

			/////////////////////////////////////////////////
			// QUERY_STRINGを取得

			if (PKWK_QUERY_STRING_MAX && strlen($arg) > PKWK_QUERY_STRING_MAX) {
				// Something nasty attack?
				lib/html.php/pkwk_common_headers();
			}
			lib/func.php/input_filter($arg); // \0 除去

			lib/mbstring.php/mb_convert_variables(SOURCE_ENCODING, 'auto', $arg);

			/////////////////////////////////////////////////
			// QUERY_STRINGを分解してコード変換し、$_GET に上書き

			// URI を urlencode せずに入力した場合に対処する
			foreach (explode('&', $arg) as $key_and_value) {
				if (preg_match('/^([^=]+)=(.+)/', $key_and_value, $matches) &&
				    lib/mbstring.php/mb_detect_encoding($matches[2]) != 'ASCII') {
				}
			}

			/////////////////////////////////////////////////
			// GET, POST, COOKIE

			// cmdもpluginも指定されていない場合は、QUERY_STRINGをページ名InterWikiNameであるとみなす
			if (! isset($vars['cmd']) && ! isset($vars['plugin'])) {
				lib/func.php/strip_bracket($arg);
				lib/func.php/input_filter($arg);
			}

			/////////////////////////////////////////////////
			// 初期設定(ユーザ定義ルール読み込み)
			rules.ini.php
				// PukiWiki setting file

				/////////////////////////////////////////////////
				// 日時置換ルール (閲覧時に置換)
				lib/func.php/format_date(UTIME),
				lib/func.php/get_date($date_format),
				lib/func.php/get_date($time_format),

				/////////////////////////////////////////////////
				// ユーザ定義ルール(保存時に置換)
				lib/func.php/format_date(UTIME),
				lib/func.php/get_date($date_format),
				lib/func.php/get_date($time_format),

				/////////////////////////////////////////////////
				// 初期設定(その他のグローバル変数)

				// 現在時刻
				lib/func.php/format_date(UTIME);

		/////////////////////////////////////////////////
		// Main

		// Spam filtering
		if ($spam && $method != 'GET') {
			// Adjustment
			if ($_spam) {
				lib/spam.php
				lib/spam_pickup.php
				lib/spam.php/pkwk_spamfilter($method . ' to #' . $_plugin, $_page, $vars, $_method, $exitmode);
			}
		}

		// Plugin execution
		if ($plugin != '') {
			if (lib/plugin.php/exist_plugin_action($plugin)) {
				lib/plugin.php/do_plugin_action($plugin);
					call_user_func('plugin_' . $plugin . '_action');
						→プラグイン関連へ
			}
		}

		// Page output
		lib/html.php/make_search($base);

		if (isset($retvars['body']) && $retvars['body'] != '') {
		} else {
			if ($base == '' || ! is_page($base)) {
				$page  = make_search($base);
			}
			lib/convert_html.php/convert_html(get_source($base));
				Body->parse($lines);
					記法をElement系オブジェクトへ変換。
				Div->toString();
					lib/plugin.php/do_plugin_convert($this->name, $this->param);
						→プラグイン関連へ
					lib/make_link.php/make_link($text);
						lib/make_link.php/InlineConverter();
							$classname = 'Link_' . $name;
							lib/make_link.php/Link_plugin($start);
							→プラグイン関連へ
		}

		// Output
		lib/html.php/catbody($title, $page, $body);