Was habe ich mir über die API der mediawiki schon den Kopf zerbrochen und geflucht...
Im aktuellen Fall will ich einige Artikel meines Wikis in einem anderen System anzeigen, ohne dass jeder Benutzer des anderen Systems einen Wiki-Zugang benötigt. (Und natürlich soll die Wiki auch nicht öffentlich sein)
So lassen sich prima in der Wiki Arbeitsanweisungen pflegen, die dann im Arbeitssystem der Benutzer angezeigt werden können.
Bis ich aber mal dahinter kam, wie ich das, was auf https://www.mediawiki.org/wiki/API:Parsing_wikitext steht, letztendlich produktiv nutzen kann...
2. Ablauf im PHP-Skript: Token holen, einloggen und Artikel abrufen
Hier mal rein als Entwurf, wie es gehen würde:
$ch = curl_init();
// Erst Token holen
curl_setopt($ch, CURLOPT_URL,"https://wiki.mydomain.net/api.php?action=query&meta=tokens&type=login&format=json");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_COOKIEJAR, 'cookie.txt');
$result = curl_exec($ch);
if (!$json = json_decode($result, true)) die("error: $result");
$token = $json['query']['tokens']['logintoken'];
// Dann mit den Zugangsdaten des Bot-Users einloggen
// Achtung: Der Bot-Benutzername besteht aus dem eigenen Benutzernamen
// plus einem @ und dem eigentlichen Bot-Namen
curl_setopt($ch, CURLOPT_URL,"https://wiki.mydomain.net/api.php?action=login&format=json");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query(array(
'lgname' => 'wikiuser@botname',
'lgpassword' => 'strengGeheimesPasswort',
'lgtoken' => $token
)));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_COOKIEJAR, 'cookie.txt');
$result = curl_exec($ch);
if (!$json = json_decode($result, true)) die("error: $result");
if ($json['login']['result'] != "Success") die("error: $result");
// Nun die eigentliche Abfrage
// Der gewünschte Artikel wird über den GET-Parameter "page" abgefragt
// > page=Seitentitel_wie_in_der_wiki
curl_setopt($ch, CURLOPT_URL,"https://wiki.mydomain.net/api.php?action=parse&page=Seitentitel_wie_in_der_wiki&prop=text&formatversion=2&format=json");
curl_setopt($ch, CURLOPT_POST, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_COOKIEJAR, 'cookie.txt');
$result = curl_exec($ch);
if (!$json = json_decode($result, true)) die("error: $result");
echo($json['parse']['text']);
?>
Das Cookie muss unbedingt mit curl_setopt($ch, CURLOPT_COOKIEJAR, 'cookie.txt'); als Datei auf dem Server vorgehalten werden.
Ich hatte erst mit curl_setopt($ch, CURLOPT_COOKIE, $cookies); und curl_setopt($ch, CURLOPT_HEADERFUNCTION, "curlResponseHeaderCallback"); versucht, die Cookie-Daten in einer lokalen Variable zu halten. Dies funktionierte aber nur bis zum Login. Beim Seitenabruf bekam ich – wieso auch immer – einen readapierror
Letztendlich habe ich mir eine kleine PHP-Klasse zusammengebastelt, mit der ich Seiten abrufen kann:
class mediawiki {
private $url = "";
private $botuser = "";
private $botpassword = "";
private $token = null;
private $cookiefile = "cookie.txt";
private $ch = null;
public function __construct($url, $user, $pass) {
$this->url = $url;
$this->botuser = $user;
$this->botpassword = $pass;
$this->ch = curl_init();
}
public function __destruct() {
curl_close($this->ch);
}
public function setCookieFile($path) {
$this->cookiefile = $path;
}
private function getToken() {
curl_setopt($this->ch, CURLOPT_URL, $this->url."/api.php?action=query&meta=tokens&type=login&format=json");
curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($this->ch, CURLOPT_COOKIEJAR, $this->cookiefile);
$result = curl_exec($this->ch);
if (!$json = json_decode($result, true)) throw new Exception('Fehler bei Token-Bezug: '.$result);
$this->token = $json['query']['tokens']['logintoken'];
}
private function doLogin() {
if ($this->token == null) $this->getToken();
curl_setopt($this->ch, CURLOPT_URL, $this->url."/api.php?action=login&format=json");
curl_setopt($this->ch, CURLOPT_POST, 1);
curl_setopt($this->ch, CURLOPT_POSTFIELDS, http_build_query(array('lgname' => $this->botuser, 'lgpassword' => $this->botpassword, 'lgtoken' => $this->token)));
curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($this->ch, CURLOPT_COOKIEJAR, $this->cookiefile);
$result = curl_exec($this->ch);
if (!$json = json_decode($result, true)) throw new Exception('Fehler bei Login: '.$result);
if ($json['login']['result'] != "Success") throw new Exception('Fehler bei Login: '.$result);
curl_setopt($this->ch, CURLOPT_POST, 0);
}
private function cleanHTML($html) {
if (is_array($html)) return $html;
$html = preg_replace('/src="\//', 'src="'.$this->url.'/', $html);
$html = preg_replace('/href="\//', 'href="'.$this->url.'/', $html);
return $html;
}
private function getImageURL($image) {
curl_setopt($this->ch, CURLOPT_URL, $this->url."/api.php?action=query&format=json&prop=imageinfo&titles=File:$image&iiprop=url&iiurlwidth=1200");
curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($this->ch, CURLOPT_COOKIEJAR, $this->cookiefile);
$result = curl_exec($this->ch);
if (!$json = json_decode($result, true)) throw new Exception('Fehler bei Seitenabruf: '.$result);
$img = array_pop($json['query']['pages']);
return $img['imageinfo'][0]['thumburl']; // thumburl:1200px Größe - $img['imageinfo'][0]['url'] wäre das Originalbild
}
public function getArticleByPagename($name, $onlySection=null, $retry=false) {
curl_setopt($this->ch, CURLOPT_URL, $this->url."/api.php?action=parse&page=".$name."&prop=text|links|displaytitle|images&formatversion=2&format=json&disableeditsection=1&disabletoc=1".(($onlySection==null)?"":"§ion=$onlySection"));
curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($this->ch, CURLOPT_COOKIEJAR, $this->cookiefile);
$result = curl_exec($this->ch);
if (!$json = json_decode($result, true)) throw new Exception('Fehler bei Seitenabruf: '.$result);
if (isset($json['error']) && $json['error']['code'] == "readapidenied" && !$retry) { $this->doLogin(); return $this->getArticleByPagename($name, $onlySection, true); }
elseif (isset($json['error'])) throw new Exception('Fehler bei Seitenabruf: '.$result);
if (isset($json['parse']['text'])) $json['parse']['text'] = $this->cleanHTML($json['parse']['text']);
return $this->cleanHTML($json['parse']);
}
public function getArticleByID($id, $onlySection=null, $retry=false) {
curl_setopt($this->ch, CURLOPT_URL, $this->url."/api.php?action=parse&page=".$id."&prop=text|links|displaytitle|images&formatversion=2&format=json&disableeditsection=1&disabletoc=1".(($onlySection==null)?"":"§ion=$onlySection"));
curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($this->ch, CURLOPT_COOKIEJAR, $this->cookiefile);
$result = curl_exec($this->ch);
if (!$json = json_decode($result, true)) throw new Exception('Fehler bei Seitenabruf: '.$result);
if (isset($json['error']) && $json['error']['code'] == "readapidenied" && !$retry) { $this->doLogin(); return $this->getArticleByID($id, $onlySection, true); }
elseif (isset($json['error'])) throw new Exception('Fehler bei Seitenabruf: '.$result);
if (isset($json['parse']['text'])) $json['parse']['text'] = $this->cleanHTML($json['parse']['text']);
return $this->cleanHTML($json['parse']);
}
// Damit dies funktioniert, muss in der LocalSettings.php noch folgende Zeile hinzugefügt werden
// if ( defined( 'MW_API' )) { $wgGroupPermissions['*']['read'] = true; }
public function getFilePath($name=null) {
curl_setopt($this->ch, CURLOPT_URL, $this->url."/api.php?action=query&format=json&prop=imageinfo&titles=Datei:$name&iiprop=url");
curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($this->ch, CURLOPT_COOKIEJAR, $this->cookiefile);
$result = curl_exec($this->ch);
if (!$json = json_decode($result, true)) throw new Exception('Fehler bei Seitenabruf: '.$result);
if (isset($json['error']) && $json['error']['code'] == "readapidenied" && !$retry) { $this->doLogin(); return $this->getFilePath($name); }
elseif (isset($json['error'])) throw new Exception('Fehler bei Seitenabruf: '.$result);
$item = array_shift($json['query']['pages']);
return $item['imageinfo'][0]['url'];
}
}
?>
Verwendung:
$w = new mediawiki("https://my.wiki.de", "my@botusername", "mysecretbotuserpassword");
$artikel = $w->getArticleByPagename("mein_artikel");
$artikel_abschnitt = $w->getArticleByPagename("mein_artikel", "nur_der_eine_abschnitt");
Anhänge:
Probleme hatte ich noch mit Anhängen: War bei einem Artikel z.B. ein PDF angehängt und man klickt in dem über meine API verarbeiteten Text auf den Link, landet man in der Wiki und muss sich einloggen, um den Anhang sehen zu können.Bettet man das PDF in der Wicht mit Datei oder File ein, sondern mit Media enthält der Artikel einen Direktlink auf die Datei (statt einen Link zur Versionsseite der Datei), der auch von außerhalb des Mediawikis in ausgeloggtem Zustand abrufbar ist.
|
|
| Erstellt am: 10.06.2024 unter den Kategorien mediawiki . | Kommentieren |









