Mediawiki 程式說明:修訂版本之間的差異

出自六年制學程
跳轉到: 導覽搜尋
(新頁面: 分類:Mediawiki ==includes/Title.php== 而Title類中 getLocalURL 方法中負責處理 interwiki 的部分有錯,因{{…}}的關係,造成 $namespace 變成 Template ,使U...)
 
includes\User.php
 
(未顯示同用戶所作出之20次版本)
第 1 行: 第 1 行:
 
[[分類:Mediawiki]]
 
[[分類:Mediawiki]]
 +
 +
==檔案架構==
 +
<table border=1 cellspacing=0 color=black class=nicetable>
 +
<tr><th>名稱</th><th>說明</th></tr>
 +
<tr>
 +
<td> math</td>
 +
<td> 存放解析數學公式的程式碼,一般而言不會接觸到,但若是數學公式功能無法成功安裝,可藉由目錄下的資訊來除錯。</td>
 +
</tr>
 +
<tr>
 +
<td> bin</td>
 +
<td> 存放在開發MediaWiki時會用到的批次檔,一般管理者或開發者不會接觸到。</td>
 +
</tr>
 +
<tr>
 +
<td> config</td>
 +
<td> 存放預設的MediaWiki設定檔(LocalSettings.php),只會於安裝時接觸到。</td>
 +
</tr>
 +
<tr>
 +
<td> docs</td>
 +
<td> 存放說明文件,對於要擴充功能的開發者很具有參考價值。</td>
 +
</tr>
 +
<tr>
 +
<td> extensions</td>
 +
<td> 存放擴充套件之目錄,對於想要擴充功能的開發者是必須要瞭解的目錄。</td>
 +
</tr>
 +
<tr>
 +
<td> images</td>
 +
<td> 存放檔案以及圖片的目錄。</td>
 +
</tr>
 +
<tr>
 +
<td> includes</td>
 +
<td> 存放主要的程式碼,要深入瞭解MediaWiki程式架構此程式碼必深入研究。</td>
 +
</tr>
 +
<tr>
 +
<td> languages</td>
 +
<td> 存放各種語系的翻譯檔案。</td>
 +
</tr>
 +
<tr>
 +
<td> maintenance</td>
 +
<td> 存放維護程式碼,例如資料庫SQL指令、升級程式碼。</td>
 +
</tr>
 +
<tr>
 +
<td> skins</td>
 +
<td> 存放佈景主題程式碼,可用來修改軟體外觀。</td>
 +
</tr>
 +
</table>
 +
 +
==可擴充功能==
 +
<table border=1 cellspacing=0 color=black class=nicetable>
 +
<tr><th>名稱</th><th>用途</th></tr>
 +
<tr>
 +
<th> Tag Extension</th>
 +
<td> 擴充MediaWiki語法,用XML格式來方式,其語法為<b>&lt;語法名稱 參數一="參數值" 參數二="參數值"&gt;傳入內容&lt;/語法名稱&gt; </b>;Tag Extension傳回內容只能是Wiki所接受的HTML語法。</td>
 +
</tr>
 +
<tr>
 +
<th> Parser Function</th>
 +
<td> 擴充MediaWiki語法,其語法為<b>{{ #函式名稱: 參數一 | 參數二 | 參數三 }}</b>;Parser Function傳回的內容可以是Wiki語法並且參數能夠傳入MediaWiki的變數在函式中處理,例如<b>{{{CURRENTDATE}}}</b>。</td>
 +
</tr>
 +
<tr>
 +
<th> Hook</th>
 +
<td> Hook可以用來欄截MediaWiki軟體中的事件,例如儲存頁面、上傳檔案、登入…等等;在使用Hook時要指定由哪個函式來執行,語法為<b>$wgHooks['event'][] = 'function';</b>。其中的function會根據每個Hook的不同而有不同的型式,例如傳入兩個參數或是需指定一個物件,下面為傳入兩個參數的函式範例<b>someFunction($param1, $param2);</b>。</td>
 +
</tr>
 +
<tr>
 +
<th> Special Page</th>
 +
<td> 在MediaWiki中有Special Page,意思是特殊頁面,例如帳號登入、網站統計、權限管理…等較特殊的功能都會在Special Page中實作。</td>
 +
</tr>
 +
</table>
 +
===Tag Extension===
 +
擴充程式
 +
<pre>
 +
$wgExtensionFunctions[] = '掛勾函式';
 +
function 掛勾函式() {
 +
global $wgParser;
 +
$wgParser->setHook('標籤名', '標籤的實體化函式');
 +
}
 +
function 標籤的實體化函式($input) {
 +
 +
return 實體化字串;
 +
}</pre>
 +
LocalSettings.php 中
 +
include_once( "$IP/extensions/擴充程式" );
 +
 +
===Parser Function===
 +
擴充程式
 +
<pre>
 +
$wgAutoloadClasses['類別名'] = 類別定義檔;
 +
$wgHooks['ParserFirstCallInit'][] = '掛勾函式';
 +
function 掛勾函式( $parser ) {
 +
global $wgPFEnableStringFunctions, $wgPFEnableConvert;
 +
$parser->setFunctionHook( '魔術字', '類別名::方法');
 +
 +
}</pre>
 +
LocalSettings.php 中
 +
include_once( "$IP/extensions/擴充程式" );
 +
 +
==延伸套件==
 +
[http://www.mediawiki.org/wiki/Category:Extensions_by_category 分類總目錄]
 +
*嵌入影片
 +
*#參考[http://www.mediawiki.org/wiki/Extension:VideoFlash VideoFlash]
 +
*#製造 extensions/videoflash.php 。
 +
*#在 LocalSettings.php 中加「require_once("$IP/extensions/videoflash.php");」。
 +
*#在共筆頁中使用 videoflash 標籤。
 +
*解除 HTML 標籤使用限制
 +
*#找到 includes 資料夾下的 Sanitizer.php
 +
*#找到 Sanitizer 類別中的 removeHTMLtags 方法
 +
*#改變要移除 tags 的清單
 +
*嵌入含圖連結
 +
*#參考[http://www.mediawiki.org/wiki/Extension:LinkedImage LinkedImage]
 +
*#在 LocalSettings.php 中加「require_once( "$IP/extensions/LinkedImages.php" );」。
 +
*#在共筆頁中使用 videoflash 標籤。
 +
 +
==[http://svn.wikimedia.org/doc/GlobalFunctions_8php.html 全域函式]==
 +
wfFindFile($title,$options=array())
 +
找出某個檔案,傳回檔案或 false(如果檔案不存在)
 +
 +
wfLocalFile($title)
 +
傳回物件,此物件的getURL方法即可找出檔案之所在
 +
 +
wfRunHooks(事件名稱,參數陣列=array())
 +
叫用定義於 $wgHooks 之中的 hook 函式
 +
 +
==主程式==
 +
===index.php===
 +
請參考 indej.php 中丁丁的註解
 +
# $preIP = dirname( __FILE__ ); // 取得路徑
 +
# require_once( "$preIP/includes/WebStart.php" );
 +
# …
 +
# $mediaWiki->finalCleanup( $wgOut ); // by jj 輸出頁面
 +
# …
 +
====includes/Wiki.php====
 +
class MediaWiki 內的
 +
 +
方法 finalCleanup 中的:
 +
$output->output();
 +
 +
====includes/OutputPage.php====
 +
class OutputPage 內的
 +
 +
方法 output 中的:
 +
$sk->outputPage( $this );
 +
 +
====includes/SkinTemplate.php====
 +
class SkinTemplate extends Skin 內的
 +
 +
方法 outputPage 中的:
 +
$res = $tpl->execute();
 +
 +
====includes/SkinTemplate.php====
 +
abstract class QuickTemplate 抽象類別內的
 +
 +
抽象方法 execute 無內容,由其 sub class 在繼承之後實作該方法的細節。
 +
abstract public function execute();
 +
 +
====skins/Vector.php====
 +
class VectorTemplate extends QuickTemplate 類別內的
 +
 +
方法 execute ,找到 &lt;!-- bodytext --&gt;,在其下插入要顯示的部分,
 +
 +
==設定==
 +
===includes/DefaultSettings.php===
 +
$wgFileExtensions = array( 'png', 'gif', 'jpg', 'jpeg' ,'svg'); // 允許上傳的附檔名
 +
 +
==includes/WebStart.php==
 +
 +
==includes/Linker.php==
 +
Linker::normalizeSubpageLink方法;將含「.、..、/」的title正規化成合法的title
 +
 
==includes/Title.php==
 
==includes/Title.php==
而Title類中 getLocalURL 方法中負責處理 interwiki 的部分有錯,因{{…}}的關係,造成 $namespace 變成 Template ,使URL插入多餘的「Template:」,需抑制修改:
+
Title 類別內的
#$namespace = $this->getNsText();
+
#userCanRead 方法:判斷能不能讀取目前的共筆頁
#if ( $namespace != '' ) {
+
#getArticleID():查此頁是第幾層的嵌入文,最外層為1,逐層加1
# Can this actually happen? Interwikis shouldn't be parsed.
+
#getPrefixedText():未處理前的頁名
# Yes! It can in interwiki transclusion. But... it probably shouldn't.
+
#getText():處理後的頁名
# $namespace .= ':';
+
#isTalkPage()
#}
+
#setFragment( '' )
#$url = $interwiki->getURL( $namespace . $this->getDBkey() );// by jj
+
#isConversionTable()
  
 +
而Title類中 getLocalURL 方法中負責處理 interwiki 的部分有錯,因<nowiki>{{</nowiki>…}}的關係,造成 $namespace 變成 Template ,使URL插入多餘的「Template:」,需抑制修改:
 +
#$namespace = $this->getNsText();
 +
#if ( $namespace != '' ) {
 +
# Can this actually happen? Interwikis shouldn't be parsed.
 +
# Yes! It can in interwiki transclusion. But... it probably shouldn't.
 +
# $namespace .= ':';
 +
#}
 +
#$url = $interwiki->getURL( $namespace . $this->getDBkey() );// by jj
 +
 +
==includes/Article.php==
 +
Article 類別
 +
 +
見[[Mediawiki 程式說明/取段落]]
 +
==includes/User.php==
 +
User 類別
 +
 +
方法 oldCrypt 舊式編碼
 +
#$wgPasswordSalt(加鹽,預設),傳回 md5($userId.'-'.md5($password))
 +
#不加鹽,傳回 md5($password)
 +
方法 crypt 新式編碼
 +
*以 UserCryptPassword 造 hash ,原料:$password、$salt、$wgPasswordSalt
 +
*#$wgPasswordSalt(加鹽,預設),沒 $slat 就做 $salt,然後傳回 ':B:'.$salt.':'.md5($salt.'-'.md5($password))
 +
*#不加鹽,傳回 ':A:'.md5($password);
 +
方法 comparePasswords 驗證密碼
 +
*先用 UserComparePasswords 勾子函式查驗,參數為:$hash、$password、$userId
 +
*上項查不過,再看 $hash 前三字是 ':A:' 還是 ':B:'
 +
*#若為 ':A:' ,比對 md5($password) 和 $hash 第三字之後是否相同。
 +
*#若為 ':B:' ,將 $hash 第三字之後以 : 拆成 $salt, $realHash 兩段,比對 md5($salt.'-'.md5($password)) 和 $realHash 是否相同。
 +
*上兩項都查不過,比對 self::oldCrypt($password,$userId) 和 $hash 是否相同。
 +
 +
== include/Sanitizer.php==
 +
文字過濾程式。內含 Sanitizer.php,$htmlsingle,$htmlsingleonly,$htmlnest,$tabletags,$htmllist,$listtags 諸陣列,控制各種 HTML tag,如何表現,可用不可用。
  
 
==includes/parser/Parser.php==
 
==includes/parser/Parser.php==
 
本程式為 wiki 語法解析的核心。
 
本程式為 wiki 語法解析的核心。
 +
===製造分段描述陣列$Article->mParserOutput->mSections===
 +
Parser 類別中
 +
 +
parse方法叫用internalParse($text)方法=>
 +
 +
internalParse($text)中叫用formatHeadings($text,$origText,$isMain)=>
 +
 +
方法formatHeadings($text,$origText,$isMain)中做出分段描述陣列$tocraw,並以
 +
$this->mOutput->setSections($tocraw);
 +
送去給includes/parser/ParserOutput.php中的ParserOutput類別的
 +
function setSections($toc){return wfSetVar($this->mSections,$toc);}
 +
將$toc派給了$Article->mParserOutput->mSections
 +
 +
===從整篇wiki文中提取其中某段的wiki原文===
 +
private function extractSections(wiki文字,段編號,$mode,取代文)
 +
#第一段的段編號為1,餘類推。段編號0代表要拉出第一段之前的導言文字
 +
#$mode有兩個值:get或replace
 +
#extractSections只有物件內部才能叫用,外部調用者應該使用以下兩種方法getSection和replaceSection
 +
 +
public function getSection($text $section,$deftext=""){
 +
    return $this->extractSections($text,$section,"get",$deftext);
 +
}
 +
 +
public function replaceSection($oldtext,$section,$text){
 +
    return $this->extractSections($oldtext,$section,"replace",$text);
 +
}
 +
 +
===嵌入===
 +
展開<nowiki>{{</nowiki>…}之braceSubstitution函式處理流程如下:
 +
一次性替代(subst)
 +
變數
 +
魔術字訊息
 +
解析函式名稱
 +
重整 title 並做$title物件
 +
從資料表找出樣板內容
 +
內部title
 +
外部title
 +
如未找到替代文,我們也做完了,傳回wiki原文
 +
在 child frame 展開 DOM-style 並傳回其值
 +
詳解請看 includes/parser/braceSubstitution解說.php
 +
 +
===跨 wiki 嵌入===
 +
 +
LocalSettings.php中必須設:
 +
$wgEnableScaryTranscluding=true; // 預設值為假
 +
includes/db/Database.php提供資料庫呼叫的抽象層類別DatabaseBase,其中:
 +
function select(表,欄,條件,…) // 叫selectSQLText
 +
function selectSQLText(表,欄,條件,…)
 +
負責叫用資料表。
 +
 +
includes/Interwiki.php提供Interwiki類別,其中的
 +
function load(網站前置字)
 +
load方法從interwiki表中抽取網站前置字相符的資料,交給loadFromArray方法做成Interwiki物件然後回傳。
 +
 +
Parser類別中的interwikiTransclude方法負責將$title代表的跨站頁嵌入:
 +
function interwikiTransclude($title,$action){
 +
  global $wgEnableScaryTranscluding;
 +
  if(!$wgEnableScaryTranscluding){ // 如不許跨wiki嵌入
 +
    return wfMsgForContent('scarytranscludedisabled');
 +
  }
 +
  $url=$title->getFullUrl("action=$action");// 取$title的URL
 +
  if(strlen($url)>255){ // URL如太長
 +
    return wfMsgForContent('scarytranscludetoolong');
 +
  }
 +
  return $this->fetchScaryTemplateMaybeFromCache($url);// 真的嵌入
 +
}
 +
 +
Parser類別中的braceSubstitution方法有一小段負責叫用interwikiTransclude
 +
 +
function braceSubstitution(…){
 +
          …
 +
  # Interwiki transclusion
 +
  // 如outtype(ot)要求為html,就嵌入解譯後的結果
 +
  if($this->ot['html'] && !$forceRawInterwiki){
 +
    $text=$this->interwikiTransclude($title,'render');
 +
    $isHTML=true;
 +
  }else{// 否則就先取回wiki原文,再仿樣板進行預處理
 +
    $text=$this->interwikiTransclude($title,'raw');
 +
    # Preprocess it like a template
 +
    $text=$this->preprocessToDom($text,self::PTD_FOR_INCLUSION);
 +
    $isChildObj=true;
 +
  }
 +
          …
 +
}
 +
而Title類中getFullURL裡負責處理interwiki的部分有錯,需抑制修改:
 +
// 因<nowiki>{{</nowiki>…}}的關係,造成$namespace變成Template,使URL插入多餘的
 +
// 「Template:」,為糾正此錯誤須抑制修改以下各行 by jj
 +
#$namespace = wfUrlencode( $this->getNsText() );
 +
#if ( $namespace != <nowiki>''</nowiki> ) {
 +
#  # Can this actually happen? Interwikis shouldn't be parsed.
 +
#  # Yes! It can in interwiki transclusion. But... it probably shouldn't.
 +
#  $namespace .= ':';
 +
#}
 +
#$url = str_replace( '$1', $namespace . $this->mUrlform, $baseUrl );
 +
$url = str_replace( '$1', $this->mUrlform, $baseUrl );
 +
 +
[https://www.mediawiki.org/wiki/Manual:$wgEnableScaryTranscluding 跨 wiki 嵌入的說明]
 +
 +
負責取回跨 wiki 內容的方法發生問題,結果傳回[抱歉,模板https://zh.wikibooks.org/wiki/%E5%88%9D%E4%B8%AD%E6%95%B8%E5%AD%B8/%E6%A0%B9%E8%99%9F?action=render讀取失敗]。將有問題段落列在後面:
 +
function fetchScaryTemplateMaybeFromCache( $url ) {
 +
global $wgTranscludeCacheExpiry;// 跨 wiki 快取生命週期,為 3600 秒,即一小時
 +
$dbr = wfGetDB( DB_SLAVE );
 +
// 暫存條件:目前時間減跨 wiki 快取生命週期
 +
$tsCond = $dbr->timestamp( time() - $wgTranscludeCacheExpiry );
 +
// 取transcache表tc_time及tc_contents欄,條件為tc_url為$url且tc_time長於暫存條件
 +
$obj = $dbr->selectRow( 'transcache', array( 'tc_time', 'tc_contents' ),
 +
array( 'tc_url' => $url, "tc_time >= " . $dbr->addQuotes( $tsCond ) ) );
 +
// 如果找到快取內容,傳回
 +
if ( $obj ) {
 +
return $obj->tc_contents;
 +
}
 +
// 執行includes/HttpFunctions.php中MWHttpRequest類別的factory方法,以產生 HTTP 的請求物件
 +
$req = MWHttpRequest::factory( $url );
 +
// 執行請求,會得到結果狀態物件
 +
$status = $req->execute(); // Status object
 +
// 執行請求後取回的內容是空值
 +
$text = $req->getContent();
 +
// 執行請求後,結果狀態不是 OK,所以$text得到空值
 +
if ( $status->isOK() ) {
 +
$text = $req->getContent();
 +
// 執行請求後,getStatus()得 200 ,所以scarytranscludefailed-httpstatus錯誤提示不會執行
 +
} elseif ( $req->getStatus() != 200 ) { // Though we failed to fetch the content, this status is useless.
 +
return wfMessage( 'scarytranscludefailed-httpstatus', $url, $req->getStatus() /* HTTP status */ )->inContentLanguage()->text();
 +
// 執行請求後,getStatus()得 200 ,所以傳回[抱歉,模板https://zh.wikibooks.org/wiki/%E5%88%9D%E4%B8%AD%E6%95%B8%E5%AD%B8/%E6%A0%B9%E8%99%9F?action=render讀取失敗]
 +
} else {
 +
return wfMessage( 'scarytranscludefailed', $url )->inContentLanguage()->text();
 +
}
 +
// 以下更新跨 wiki 快取的欄值
 +
$dbw = wfGetDB( DB_MASTER );
 +
$dbw->replace( 'transcache', array( 'tc_url' ), array(
 +
'tc_url' => $url,
 +
'tc_time' => $dbw->timestamp( time() ),
 +
'tc_contents' => $text)
 +
);
 +
// 執行請求後,結果狀態如果是OK,傳回$text
 +
return $text;
 +
}

2014年8月31日 (日) 20:07的最新修訂版本


檔案架構

名稱說明
math 存放解析數學公式的程式碼,一般而言不會接觸到,但若是數學公式功能無法成功安裝,可藉由目錄下的資訊來除錯。
bin 存放在開發MediaWiki時會用到的批次檔,一般管理者或開發者不會接觸到。
config 存放預設的MediaWiki設定檔(LocalSettings.php),只會於安裝時接觸到。
docs 存放說明文件,對於要擴充功能的開發者很具有參考價值。
extensions 存放擴充套件之目錄,對於想要擴充功能的開發者是必須要瞭解的目錄。
images 存放檔案以及圖片的目錄。
includes 存放主要的程式碼,要深入瞭解MediaWiki程式架構此程式碼必深入研究。
languages 存放各種語系的翻譯檔案。
maintenance 存放維護程式碼,例如資料庫SQL指令、升級程式碼。
skins 存放佈景主題程式碼,可用來修改軟體外觀。

可擴充功能

名稱用途
Tag Extension 擴充MediaWiki語法,用XML格式來方式,其語法為<語法名稱 參數一="參數值" 參數二="參數值">傳入內容</語法名稱> ;Tag Extension傳回內容只能是Wiki所接受的HTML語法。
Parser Function 擴充MediaWiki語法,其語法為{{ #函式名稱: 參數一 | 參數二 | 參數三 }};Parser Function傳回的內容可以是Wiki語法並且參數能夠傳入MediaWiki的變數在函式中處理,例如{{{CURRENTDATE}}}
Hook Hook可以用來欄截MediaWiki軟體中的事件,例如儲存頁面、上傳檔案、登入…等等;在使用Hook時要指定由哪個函式來執行,語法為$wgHooks['event'][] = 'function';。其中的function會根據每個Hook的不同而有不同的型式,例如傳入兩個參數或是需指定一個物件,下面為傳入兩個參數的函式範例someFunction($param1, $param2);
Special Page 在MediaWiki中有Special Page,意思是特殊頁面,例如帳號登入、網站統計、權限管理…等較特殊的功能都會在Special Page中實作。

Tag Extension

擴充程式

$wgExtensionFunctions[] = '掛勾函式';
function 掛勾函式() {
	global $wgParser;
	$wgParser->setHook('標籤名', '標籤的實體化函式');
}
function 標籤的實體化函式($input) {
	…
	return 實體化字串;
}

LocalSettings.php 中

include_once( "$IP/extensions/擴充程式" );

Parser Function

擴充程式

$wgAutoloadClasses['類別名'] = 類別定義檔;
$wgHooks['ParserFirstCallInit'][] = '掛勾函式';
function 掛勾函式( $parser ) {
	global $wgPFEnableStringFunctions, $wgPFEnableConvert;
	$parser->setFunctionHook( '魔術字', '類別名::方法');
	…
}

LocalSettings.php 中

include_once( "$IP/extensions/擴充程式" );

延伸套件

分類總目錄

  • 嵌入影片
    1. 參考VideoFlash
    2. 製造 extensions/videoflash.php 。
    3. 在 LocalSettings.php 中加「require_once("$IP/extensions/videoflash.php");」。
    4. 在共筆頁中使用 videoflash 標籤。
  • 解除 HTML 標籤使用限制
    1. 找到 includes 資料夾下的 Sanitizer.php
    2. 找到 Sanitizer 類別中的 removeHTMLtags 方法
    3. 改變要移除 tags 的清單
  • 嵌入含圖連結
    1. 參考LinkedImage
    2. 在 LocalSettings.php 中加「require_once( "$IP/extensions/LinkedImages.php" );」。
    3. 在共筆頁中使用 videoflash 標籤。

全域函式

wfFindFile($title,$options=array()) 找出某個檔案,傳回檔案或 false(如果檔案不存在)

wfLocalFile($title) 傳回物件,此物件的getURL方法即可找出檔案之所在

wfRunHooks(事件名稱,參數陣列=array()) 叫用定義於 $wgHooks 之中的 hook 函式

主程式

index.php

請參考 indej.php 中丁丁的註解

  1. $preIP = dirname( __FILE__ ); // 取得路徑
  2. require_once( "$preIP/includes/WebStart.php" );
  3. $mediaWiki->finalCleanup( $wgOut ); // by jj 輸出頁面

includes/Wiki.php

class MediaWiki 內的

方法 finalCleanup 中的:

$output->output();

includes/OutputPage.php

class OutputPage 內的

方法 output 中的:

$sk->outputPage( $this );

includes/SkinTemplate.php

class SkinTemplate extends Skin 內的

方法 outputPage 中的:

$res = $tpl->execute();

includes/SkinTemplate.php

abstract class QuickTemplate 抽象類別內的

抽象方法 execute 無內容,由其 sub class 在繼承之後實作該方法的細節。

abstract public function execute();

skins/Vector.php

class VectorTemplate extends QuickTemplate 類別內的

方法 execute ,找到 <!-- bodytext -->,在其下插入要顯示的部分,

設定

includes/DefaultSettings.php

$wgFileExtensions = array( 'png', 'gif', 'jpg', 'jpeg' ,'svg'); // 允許上傳的附檔名

includes/WebStart.php

includes/Linker.php

Linker::normalizeSubpageLink方法;將含「.、..、/」的title正規化成合法的title

includes/Title.php

Title 類別內的

  1. userCanRead 方法:判斷能不能讀取目前的共筆頁
  2. getArticleID():查此頁是第幾層的嵌入文,最外層為1,逐層加1
  3. getPrefixedText():未處理前的頁名
  4. getText():處理後的頁名
  5. isTalkPage()
  6. setFragment( )
  7. isConversionTable()

而Title類中 getLocalURL 方法中負責處理 interwiki 的部分有錯,因{{…}}的關係,造成 $namespace 變成 Template ,使URL插入多餘的「Template:」,需抑制修改:

#$namespace = $this->getNsText();
#if ( $namespace !=  ) {
	# Can this actually happen? Interwikis shouldn't be parsed.
	# Yes! It can in interwiki transclusion. But... it probably shouldn't.
#	$namespace .= ':';
#}
#$url = $interwiki->getURL( $namespace . $this->getDBkey() );// by jj

includes/Article.php

Article 類別

Mediawiki 程式說明/取段落

includes/User.php

User 類別

方法 oldCrypt 舊式編碼

  1. $wgPasswordSalt(加鹽,預設),傳回 md5($userId.'-'.md5($password))
  2. 不加鹽,傳回 md5($password)

方法 crypt 新式編碼

  • 以 UserCryptPassword 造 hash ,原料:$password、$salt、$wgPasswordSalt
    1. $wgPasswordSalt(加鹽,預設),沒 $slat 就做 $salt,然後傳回 ':B:'.$salt.':'.md5($salt.'-'.md5($password))
    2. 不加鹽,傳回 ':A:'.md5($password);

方法 comparePasswords 驗證密碼

  • 先用 UserComparePasswords 勾子函式查驗,參數為:$hash、$password、$userId
  • 上項查不過,再看 $hash 前三字是 ':A:' 還是 ':B:'
    1. 若為 ':A:' ,比對 md5($password) 和 $hash 第三字之後是否相同。
    2. 若為 ':B:' ,將 $hash 第三字之後以 : 拆成 $salt, $realHash 兩段,比對 md5($salt.'-'.md5($password)) 和 $realHash 是否相同。
  • 上兩項都查不過,比對 self::oldCrypt($password,$userId) 和 $hash 是否相同。

include/Sanitizer.php

文字過濾程式。內含 Sanitizer.php,$htmlsingle,$htmlsingleonly,$htmlnest,$tabletags,$htmllist,$listtags 諸陣列,控制各種 HTML tag,如何表現,可用不可用。

includes/parser/Parser.php

本程式為 wiki 語法解析的核心。

製造分段描述陣列$Article->mParserOutput->mSections

Parser 類別中

parse方法叫用internalParse($text)方法=>

internalParse($text)中叫用formatHeadings($text,$origText,$isMain)=>

方法formatHeadings($text,$origText,$isMain)中做出分段描述陣列$tocraw,並以

$this->mOutput->setSections($tocraw);

送去給includes/parser/ParserOutput.php中的ParserOutput類別的

function setSections($toc){return wfSetVar($this->mSections,$toc);}

將$toc派給了$Article->mParserOutput->mSections

從整篇wiki文中提取其中某段的wiki原文

private function extractSections(wiki文字,段編號,$mode,取代文)
  1. 第一段的段編號為1,餘類推。段編號0代表要拉出第一段之前的導言文字
  2. $mode有兩個值:get或replace
  3. extractSections只有物件內部才能叫用,外部調用者應該使用以下兩種方法getSection和replaceSection
public function getSection($text $section,$deftext=""){
   return $this->extractSections($text,$section,"get",$deftext);
}
public function replaceSection($oldtext,$section,$text){
   return $this->extractSections($oldtext,$section,"replace",$text);
}

嵌入

展開{{…}之braceSubstitution函式處理流程如下:

一次性替代(subst)
變數
魔術字訊息
解析函式名稱
重整 title 並做$title物件
從資料表找出樣板內容

內部title 外部title

如未找到替代文,我們也做完了,傳回wiki原文
在 child frame 展開 DOM-style 並傳回其值

詳解請看 includes/parser/braceSubstitution解說.php

跨 wiki 嵌入

LocalSettings.php中必須設:

$wgEnableScaryTranscluding=true;	// 預設值為假

includes/db/Database.php提供資料庫呼叫的抽象層類別DatabaseBase,其中:

function select(表,欄,條件,…)		// 叫selectSQLText
function selectSQLText(表,欄,條件,…)

負責叫用資料表。

includes/Interwiki.php提供Interwiki類別,其中的

function load(網站前置字)

load方法從interwiki表中抽取網站前置字相符的資料,交給loadFromArray方法做成Interwiki物件然後回傳。

Parser類別中的interwikiTransclude方法負責將$title代表的跨站頁嵌入:

function interwikiTransclude($title,$action){
  global $wgEnableScaryTranscluding;
  if(!$wgEnableScaryTranscluding){	// 如不許跨wiki嵌入
    return wfMsgForContent('scarytranscludedisabled');
  }
  $url=$title->getFullUrl("action=$action");// 取$title的URL
  if(strlen($url)>255){		// URL如太長
    return wfMsgForContent('scarytranscludetoolong');
  }
  return $this->fetchScaryTemplateMaybeFromCache($url);// 真的嵌入
}

Parser類別中的braceSubstitution方法有一小段負責叫用interwikiTransclude

function braceSubstitution(…){
         …
  # Interwiki transclusion
  // 如outtype(ot)要求為html,就嵌入解譯後的結果
  if($this->ot['html'] && !$forceRawInterwiki){
    $text=$this->interwikiTransclude($title,'render');
    $isHTML=true;
  }else{// 否則就先取回wiki原文,再仿樣板進行預處理
    $text=$this->interwikiTransclude($title,'raw');
    # Preprocess it like a template
    $text=$this->preprocessToDom($text,self::PTD_FOR_INCLUSION);
    $isChildObj=true;
  }
         …
}

而Title類中getFullURL裡負責處理interwiki的部分有錯,需抑制修改:

// 因{{…}}的關係,造成$namespace變成Template,使URL插入多餘的
// 「Template:」,為糾正此錯誤須抑制修改以下各行 by jj
#$namespace = wfUrlencode( $this->getNsText() );
#if ( $namespace != '' ) {
#  # Can this actually happen? Interwikis shouldn't be parsed.
#  # Yes! It can in interwiki transclusion. But... it probably shouldn't.
#  $namespace .= ':';
#}
#$url = str_replace( '$1', $namespace . $this->mUrlform, $baseUrl );
$url = str_replace( '$1', $this->mUrlform, $baseUrl );

跨 wiki 嵌入的說明

負責取回跨 wiki 內容的方法發生問題,結果傳回[抱歉,模板https://zh.wikibooks.org/wiki/%E5%88%9D%E4%B8%AD%E6%95%B8%E5%AD%B8/%E6%A0%B9%E8%99%9F?action=render讀取失敗]。將有問題段落列在後面:

function fetchScaryTemplateMaybeFromCache( $url ) {
	global $wgTranscludeCacheExpiry;// 跨 wiki 快取生命週期,為 3600 秒,即一小時
	$dbr = wfGetDB( DB_SLAVE );
	// 暫存條件:目前時間減跨 wiki 快取生命週期
	$tsCond = $dbr->timestamp( time() - $wgTranscludeCacheExpiry );
	// 取transcache表tc_time及tc_contents欄,條件為tc_url為$url且tc_time長於暫存條件
	$obj = $dbr->selectRow( 'transcache', array( 'tc_time', 'tc_contents' ),
			array( 'tc_url' => $url, "tc_time >= " . $dbr->addQuotes( $tsCond ) ) );
	// 如果找到快取內容,傳回
	if ( $obj ) {
		return $obj->tc_contents;
	}
	// 執行includes/HttpFunctions.php中MWHttpRequest類別的factory方法,以產生 HTTP 的請求物件
	$req = MWHttpRequest::factory( $url );
	// 執行請求,會得到結果狀態物件
	$status = $req->execute(); // Status object
	// 執行請求後取回的內容是空值
	$text = $req->getContent();
	// 執行請求後,結果狀態不是 OK,所以$text得到空值
	if ( $status->isOK() ) {
		$text = $req->getContent();
	// 執行請求後,getStatus()得 200 ,所以scarytranscludefailed-httpstatus錯誤提示不會執行
	} elseif ( $req->getStatus() != 200 ) { // Though we failed to fetch the content, this status is useless.
		return wfMessage( 'scarytranscludefailed-httpstatus', $url, $req->getStatus() /* HTTP status */ )->inContentLanguage()->text();
	// 執行請求後,getStatus()得 200 ,所以傳回[抱歉,模板https://zh.wikibooks.org/wiki/%E5%88%9D%E4%B8%AD%E6%95%B8%E5%AD%B8/%E6%A0%B9%E8%99%9F?action=render讀取失敗] 
	} else {
		return wfMessage( 'scarytranscludefailed', $url )->inContentLanguage()->text();
	}
	// 以下更新跨 wiki 快取的欄值
	$dbw = wfGetDB( DB_MASTER );
	$dbw->replace( 'transcache', array( 'tc_url' ), array(
		'tc_url' => $url,
		'tc_time' => $dbw->timestamp( time() ),
		'tc_contents' => $text)
	);
	// 執行請求後,結果狀態如果是OK,傳回$text
	return $text;
}