[
DevFaqEagleFr ] [
In English ] [
En Espanol ] [
Deutsch? ]
Les besoins et la doc' utilisateur sont dans
DocFaqEagleFr
La solution mise à place à l'heure actuelle
C'est une solution "rapide" qui prend en compte les contraintes d'hébergement facile (PHP pour le langage et MySql pour le backend SQL) ainsi que l'utilisation de wikini comme moyen de travail collaboratif style wiki.
Paramètres en entrée
Une page contenant le squelette du fichier xml
DocBook à passer en paramètre au script eagle-faq.php (eagle-faq.php?page=
DocBookFr).
La page squelette est propre à chaque langue. Pour le français, c'est
DocBookFr.
Algorithme
Cette page au format xml
DocBook est parsée à la recherche de balise de la sorte:
<qandadiv id="
FaqGeneralFr">
<title>Questions générales</title>
</qandadiv>
<qandadiv id="
FaqModemFr">
<title>Questions modem</title>
</qandadiv>
et pour chaque balise, remplace le tout par le contenu de la page. On peut donc rajouter des pages, changer leur ordre, traduire les méta-informations (copyright, abstract...).
Visualisation du résultat
http://faq.eagle-usb.org/eagle-faq.php?page=DocBookFr
Il faut sauver la page résultante avec l'entension .xml.
Pour tester ce que ca donne une fois transformé, se référer aux explications de la page
DocBook.
Code du script php
http://faq.eagle-usb.org/faqeagle/eagle-faq.php:
<?php
//
// Script to produce a docbook document from the eagle-faq wiki
// Usage: http://my.host.com/path_to_wakka/eagle-faq.php[?page=DocBookFr]
//
// Include wakka configuration file (for database connection parameters)
// (An array named wakkaConfig is created)
$wakka_config_file = 'wakka.config.php';
include($wakka_config_file);
// Get the page parameter
$page = array_key_exists('page', $_REQUEST) ? $_REQUEST['page'] : 'DocBookFr';
// Database connection
$db = mysql_connect($wakkaConfig['mysql_host'], $wakkaConfig['mysql_user'], $wakkaConfig['mysql_password']);
mysql_select_db($wakkaConfig['mysql_database'], $db);
// Read the template docbook document
$sql = "SELECT body FROM ".$wakkaConfig['table_prefix']."pages WHERE tag='$page' AND latest='Y'";
$res = mysql_query($sql, $db);
list($xml) = mysql_fetch_array($res);
if ($xml) {
function wakka2callback($things) {
$thing = $things[1];
$result='';
static $oldIndentLevel = 0;
static $oldIndentLength= 0;
static $indentClosers = array();
static $newIndentSpace= array();
// bold
if ($thing == "**") {
static $bold = 0;
return (++$bold % 2 ? '<emphasis role="bold">' : '</emphasis>');
}
// italic
else if ($thing == "//") {
static $italic = 0;
return (++$italic % 2 ? '<emphasis role="italic">' : '</emphasis>');
}
// underlinue
else if ($thing == "__")
{
static $underline = 0;
return (++$underline % 2 ? '<emphasis role="underline">' : '</emphasis>');
}
// monospace
else if ($thing == "##") {
static $monospace = 0;
return (++$monospace % 2 ? '<emphasis role="highlight">' : '</emphasis>');
}
// escaped text
else if (preg_match("/^""(.*)""$/s", $thing, $matches)) {
return $matches[1];
}
// urls
else if (preg_match("/^([a-z]+:\/\/\S+?)([^[:alnum:]^\/])?$/", $thing, $matches)) {
$url = $matches[1];
return "<ulink url=\"$url\" />".$matches[2];
}
// forced links
// \S : any character that is not a whitespace character
// \s : any whitespace character
else if (preg_match("/^\[\[(\S*)(\s+(.+))?\]\]$/", $thing, $matches)) {
list (, $url, , $text) = $matches;
if ($url) {
if (!$text) return "<ulink url=\"$url\" />";
else return "<ulink url=\"$url\">$text</ulink>";
}
else return "";
}
// indented text
else if (preg_match("/\n(\t+|([ ]{1})+)(-|([0-9,a-z,A-Z]+)\))?/s", $thing, $matches)) {
// new line
// find out which indent type we want
$newIndentType = $matches[3];
if (!$newIndentType) { $opener = "<div class=\"indent\">"; $closer = "</div>"; $br = 1; }
else if ($newIndentType == "-") { $opener = "<itemizedlist>\n"; $closer = "</listitem>\n</itemizedlist>"; $li = 1; }
else { $opener = "<orderedlist type=\"".$matches[4]."\">\n"; $closer = "</listitem>\n</orderedlist>"; $li = 1; }
// get new indent level
if (strpos($matches[1],"\t")) $newIndentLevel = strlen($matches[1]);
else {
$newIndentLevel=$oldIndentLevel;
$newIndentLength = strlen($matches[1]);
if ($newIndentLength>$oldIndentLength)
{
$newIndentLevel++;
$newIndentSpace[$newIndentLength]=$newIndentLevel;
}
else if ($newIndentLength<$oldIndentLength)
$newIndentLevel=$newIndentSpace[$newIndentLength];
}
$op=0;
if ($newIndentLevel > $oldIndentLevel)
{
for ($i = 0; $i < $newIndentLevel - $oldIndentLevel; $i++)
{
$result .= $opener;
$op=1;
array_push($indentClosers, $closer);
}
}
else if ($newIndentLevel < $oldIndentLevel)
{
for ($i = 0; $i < $oldIndentLevel - $newIndentLevel; $i++)
{
$op=1;
$result .= array_pop($indentClosers);
if ($oldIndentLevel && $li) $result .= "</li>";
}
}
if (isset($li) && $op) $result .= "<listitem>";
else if (isset($li))
$result .= "</listitem>\n<listitem>";
$oldIndentLevel = $newIndentLevel;
$oldIndentLength= $newIndentLength;
return $result;
}
// new lines
else if ($thing == "\n") {
// if we got here, there was no tab in the next line; this means that we can close all open indents.
$c = count($indentClosers);
for ($i = 0; $i < $c; $i++) {
$result .= array_pop($indentClosers);
$br = 0;
}
$oldIndentLevel = 0;
$oldIndentLength= 0;
$newIndentSpace=array();
$result .= "\n";
return $result;
}
// wiki links!
else if (preg_match("/^[A-Z][a-z]+[A-Z,0-9][A-Z,a-z,0-9]*$/s", $thing)) {
//return $wiki->Link($thing);
return $thing;
}
// if we reach this point, it must have been an accident.
return $thing;
}
// Function producing docbook qanda entry from wakka formatted text
function format_qanda($text) {
$xml = array();
$xml[] = '<qandaentry>';
// Split the text to questions and answers
$para = explode("\n\n", $text);
$questions = explode("\n", array_shift($para));
array_shift($questions);
// test if the first line contains a question or the information line [102 new ...]
if (!ereg('^={2,5}.+={2,5}$', trim($questions[0]))) array_shift($questions);
// format the question[s]
foreach ($questions as $q) {
$xml[] = '<question>';
$xml[] = '<para>';
preg_match('|^={2,5}([^=]*)={2,5}$|', trim($q), $matches);
$xml[] = trim($matches[1]);
$xml[] = '</para>';
$xml[] = '</question>';
}
// format the answer
$xml[] = '<answer>';
foreach ($para as $p) {
if (!trim($p)) continue;
$xml[] = '<para>';
$p.="\n";
// Format the paragraphs, functions from wakka.php formatter
$p = preg_replace_callback(
"/(\*\*|\/\/|__|\#\#|".
""".*?""|".
"\b[a-z]+:\/\/\S+|".
"\[\[.*?\]\]|".
"\n(\t+|([ ]{1})+)(-|[0-9,a-z,A-Z]+\))?|".
"\b([A-Z][a-z]+[A-Z,0-9][A-Z,a-z,0-9]*)\b|".
"\n)/ms", "wakka2callback", $p);
$xml[] = $p;
$xml[] = '</para>';
}
$xml[] = '</answer>';
$xml[] = '</qandaentry>';
return implode("\n", $xml);
}
// Get the faq names to include in the document
$faq_array = array();
preg_match_all('|<qandadiv id="(Faq[A-Z][A-Za-z]*)">\s*<title>([^<]*)</title>\s*</qandadiv>|', $xml, $faq_array);
// Loop on each match
foreach ($faq_array[1] as $faq_index=>$faq_name) {
// Select the body of the faq
$sql = "SELECT body FROM ".$wakkaConfig['table_prefix']."pages WHERE tag='$faq_name' AND latest='Y'";
$res = mysql_query($sql, $db);
list($body) = mysql_fetch_array($res);
// Convert special chars to entities; (&,<,>,',")
$body = htmlspecialchars($body, ENT_QUOTES);
// Put each question and answer in an array
$questions = split('-{4,}', $body);
array_shift($questions);
// Process qanda one after the other
$qanda_entries = array();
foreach ($questions as $q) {
//$q = trim($q);
if ($q) $qanda_entries[] = format_qanda($q);
}
// Prepare the faq_array table for the replacement
$faq_array[1][$faq_index] = "<qandadiv>\n<title>\n".trim($faq_array[2][$faq_index])."\n</title>".implode("\n", $qanda_entries)."\n</qandadiv>";
$faq_array[0][$faq_index] = '|'.$faq_array[0][$faq_index].'|';
}
$xml = preg_replace($faq_array[0], $faq_array[1], $xml);
header("Content-type: text/xml");
print($xml);
}
else {
// Warn about wrong page parameter
print('<html><header><title>Eagle-FAQ</title></header><body>');
print("Page $page is not a valid wikini page to produce a xml docbook document");
print('</body></html>');
}
// Cleanning up a bit
mysql_close($db);
?>
Proposition de modification, d'amélioration, etc... ci dessous
[20031124] Sous forme de conseils en texte "pure" et/ou sous forme de bout de code php. --
FrankJ
[20031203] Intégration à
WikiNi sous la forme d'un handler : je peux éventuellement vous filer un coup de main une fois que votre code sera stabilisé. --
CharlesNepote
[20031203] Ben en fait, ce code est une solution temporaire. On étudie des solutions alternatives (voir
DocFaqEagleFr) car:
- La syntaxe de wikini n'est pas prévu pour faire du docbook, ce n'est évidemment pas son but.
- L'ajout d'une syntaxe n'est pas prevu en standard (malgre un champ handler dans la table wiki_pages qui n'est pas exploité)
Ceci dit, si l'ajout de syntaxe est une feature qui pourrait être intégré à wikini, alors on pourrait considérer l'option d'inclure un handler pour la syntaxe
WikiText. --
FrankJ