Php
如何將內容添加到 mediawiki 中的所有頁面?
TL;DR:如何向每個頁面的內容(不是標題或全域模板)添加文本(通知)?
(非常)長問題的背景:我計劃將 MediaWiki 遷移到另一個 wiki。wiki 的內容是從之前更舊的 wiki 遷移而來的(生成了有關格式的錯誤),隨著時間的推移而增長,現在大部分已經過時。這就是為什麼我們要從空白 wiki 開始並手動遷移內容,丟棄和/或更新過時的頁面。
為了使這更容易,我想在每個現有頁面的頂部添加一個文本塊,特別是一個模板,通知該頁面尚未遷移或丟棄,以及收集所有這些頁面的類別(例如類別:migration_pending) . 然後,每個使用者都應該瀏覽他負責的頁面,將內容複製到新的 wiki 並將模板更改為另一個模板,將頁面標記為已遷移 (category:migration_done) 或丟棄 (category:migration_discarded)。通過這種方式,應該可以在不忘記任何重要內容的情況下獲得一個乾淨、最新的 wiki。
Replace_Text 擴展不成功,所以我結束了編寫自己的使用 MediaWiki API 的腳本。
我從這裡開始使用登錄腳本並編寫了這個腳本:
#!/usr/bin/php <?php $settings['wikiroot'] = "https://server/mediawiki"; $settings['user'] = "username"; $settings['pass'] = "password"; // $settings['domain'] = 'Windows'; $settings['cookiefile'] = "cookies.tmp"; $prepend = "{{migration_pending}}\n\n"; function httpRequest($url, $post="") { global $settings; $ch = curl_init(); //Change the user agent below suitably curl_setopt($ch, CURLOPT_USERAGENT, 'MediaWiki Migration Script 0.1'); curl_setopt($ch, CURLOPT_URL, ($url)); curl_setopt($ch, CURLOPT_ENCODING, "UTF-8" ); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_COOKIEFILE, $settings['cookiefile']); curl_setopt($ch, CURLOPT_COOKIEJAR, $settings['cookiefile']); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); if (!empty($post)) curl_setopt($ch,CURLOPT_POSTFIELDS,$post); //UNCOMMENT TO DEBUG TO output.tmp //curl_setopt($ch, CURLOPT_VERBOSE, true); // Display communication with server //$fp = fopen("output.tmp", "w"); //curl_setopt($ch, CURLOPT_STDERR, $fp); // Display communication with server $xml = curl_exec($ch); if (!$xml) { throw new Exception("Error getting data from server ($url): " . curl_error($ch)); } //var_dump($xml); curl_close($ch); return $xml; } function login ($user, $pass, $token='') { global $settings; $url = $settings['wikiroot'] . "/api.php?action=login&format=xml"; $params = "action=login&lgname=$user&lgpassword=$pass"; if (!empty($settings['domain'])) { $params .= "&lgdomain=" . $settings['domain']; } if (!empty($token)) { $params .= "&lgtoken=$token"; } $data = httpRequest($url, $params); if (empty($data)) { throw new Exception("No data received from server. Check that API is enabled."); } $xml = simplexml_load_string($data); if (!empty($token)) { //Check for successful login $expr = "/api/login[@result='Success']"; $result = $xml->xpath($expr); if(!count($result)) { throw new Exception("Login failed"); } } else { $expr = "/api/login[@token]"; $result = $xml->xpath($expr); if(!count($result)) { throw new Exception("Login token not found in XML"); } } return $result[0]->attributes()->token; } try { global $settings; $token = login($settings['user'], $settings['pass']); login($settings['user'], $settings['pass'], $token); $star = "*"; $dash1 = "-1"; // get edit token $result = httpRequest($settings['wikiroot'] . "/api.php?action=query&format=json&prop=info|revisions&intoken=edit&titles=Main%20Page"); $result = json_decode($result); $editToken = $result->query->pages->$dash1->edittoken; // only from namespace: apnamespace=100 $result = httpRequest($settings['wikiroot'] . "/api.php?action=query&list=allpages&format=json&aplimit=5000&apnamespace=100"); $result = json_decode($result); $allpages = $result->query->allpages; foreach ($allpages as $page) { echo "Fetching '{$page->title}' ({$page->pageid})...\n"; $revisions = httpRequest(sprintf($settings['wikiroot'] . "/api.php?action=query&prop=revisions&rvlimit=1&format=json&rvprop=content&titles=%s", urlencode($page->title))); $revisions = json_decode($revisions); if (isset($revisions->error)) { echo "ERROR: " . $revisions->error->info . "\n"; continue; } $content = $revisions->query->pages->{$page->pageid}->revisions[0]->$star; if (preg_match("/\{\{migration_/", $content)) { echo "Already marked ... skipping.\n"; continue; } echo "Updating..."; // add text to content and edit page $content = $prepend . $content; $post = sprintf("title=%s&text=%s&token=%s", urlencode($page->title), urlencode($content), urlencode($editToken)); $result = httpRequest($settings['wikiroot'] . "/api.php?action=edit&format=json", $post); echo "done\n"; } echo ("Finished (".sizeof($allpages)." pages).\n"); } catch (Exception $e) { die("FAILED: " . $e->getMessage()); } ?>
該腳本的基本作用是:
使用現有帳戶登錄
獲得一個允許它進行編輯操作的令牌
檢索給定命名空間內所有頁面的列表
對於每一頁:
- 從最新版本中獲取內容
- 向內容添加預定義文本
- 用新內容保存頁面
一些附加說明:
- 確保您要使用的使用者存在並且對所有需要的命名空間具有寫入權限。
- 將使用者添加到“Bot”組。這將消除一些限制,例如允許機器人以 5000 人為一組進行批量操作,而不是像普通使用者那樣以 500 人為一組進行批量操作。不確定這個腳本是否有必要,但它不會受到傷害。
- 當使用 LdapAuthentication 之類的身份驗證擴展時
domain
,必須設置該參數。並且必須將其設置為LDAP 源的名稱LocalSettings.php
,而不是域的實際名稱。- 在執行腳本之前禁用電子郵件通知。否則,每個在 wiki 中觀看頁面的人都會收到他觀看的每個更改頁面的通知。對我來說,這是
$wgEnableEmail = false;
和$wgEnotifWatchlist = false;
在LocalSettings.php
.- 我從命令行執行腳本,速度不快,1000 多頁需要幾分鐘。如果我通過網路伺服器執行它肯定會超時。
最後但同樣重要的是,
migration_pending
我添加到 MediaWiki 的模板:{|class=warningbox | [[Image:Emblem-important.png]] | This page hasn't been audited yet, the information on it could be outdated. If you are responsible for this page, please check it's content. If it is still current, add it to the new wiki and change this template to <nowiki>{{Migration_done}}</nowiki>. If the information on this page is not needed anymore change the template to <nowiki>{{Migration_discarded}}</nowiki> |} [[Category:MigrationPending]]
這對我們之前使用的表格使用 CSS 類,並將頁面添加到特定類別。
migration_done
我添加了與migration_discarded
相應類別類似的模板。