somekey wikipedia, blabla
some wikitext
#wikipedia [http://www.wikipedia.org Wikipedia]
#somekey pmid=12345678
#abook isbn=0-4714-1761-0 // figure 5, page 72 is particularly interesting
*/
require_once('nusoap/nusoap.php');
// This module reserves the names starting with "Biblio"
// Registration of this extension
$wgExtensionFunctions[] = "BiblioExtension";
function BiblioExtension() {
global $wgParser;
// register the extension with the WikiText parser
// the first parameter is the name of the new tag.
// In this case it defines the tag ...
// the second parameter is the callback function for
// processing the text between the tags
$wgParser->setHook("cite", "Biblio_render_cite");
$wgParser->setHook("biblio", "Biblio_render_biblio");
}
// XML parsing
class Biblio_xml {
var $parser;
var $data;
function tag_open($parser, $name, $attrs) {
$data['name'] = $name;
$data['attributes'] = $attrs;
$this->data[] = $data;
}
function tag_close($parser, $name) {
if (count($this->data) > 1) {
$data = array_pop($this->data);
$index = count($this->data) - 1;
$this->data[$index]['child'][] = $data;
}
}
function cdata($parser, $s) {
$index = count($this->data) - 1;
if (array_key_exists('content',$this->data[$index]))
$this->data[$index]['content'] .= $s;
else
$this->data[$index]['content'] = $s;
}
function parse ($text) {
$this->parser = xml_parser_create();
xml_set_object($this->parser, $this);
xml_set_element_handler($this->parser, "tag_open", "tag_close");
xml_set_character_data_handler($this->parser, "cdata");
xml_parse($this->parser, $text, true);
xml_parser_free($this->parser);
return $this->data;
}
}
class Biblio {
var $BiblioVersion = "0.7.5+1";
// Array functions which avoid notices if E_NOTICE is used
function get($array, $key) {
if (is_array($array) && array_key_exists($key, $array))
return $array[$key];
else
return NULL;
}
// Reading text from a URL
function get_url($url) {
$old_url_fopen = ini_set("allow_url_fopen", true);
$result = @implode('', file($url));
ini_set("allow_url_fopen", $old_url_fopen);
return $result;
}
// Management of the citation indices
// (order in which they appear in the text)
var $Citations = array();
// find the number of the reference if already cited or assign a new one
function CitationIndex($key) {
if (array_key_exists($key, $this->Citations)) {
return $this->Citations[$key];
} else {
$index = count($this->Citations);
$this->Citations[$key] = $index;
return $index;
}
}
// Retrieve PubMed entry from their SOAP webservice
function eSummary($pmids) {
$soap_result = array('DocSum' => array());
if (count($pmids) == 0) { return $soap_result; }
$server_url =
'http://eutils.ncbi.nlm.nih.gov/entrez/eutils/soap/eutils.wsdl';
$operation = 'run_eSummary';
$param = array('db' => 'pubmed',
'id' => implode(",", $pmids));
$proxyhost = isset($_POST['proxyhost']) ? $_POST['proxyhost'] : '';
$proxyport = isset($_POST['proxyport']) ? $_POST['proxyport'] : '';
$proxyusername =
isset($_POST['proxyusername']) ? $_POST['proxyusername'] : '';
$proxypassword =
isset($_POST['proxypassword']) ? $_POST['proxypassword'] : '';
$client =
new soapclient($server_url, true,
$proxyhost, $proxyport,
$proxyusername, $proxypassword);
$err = $client->getError();
if (!$err) {
$result = $client->call($operation, array('parameters' => $param),
'', '', false, true);
if (!$client->fault) {
$err = $client->getError();
if ($err) {
return $soap_result;
} else {
$soap_result = $result;
}
}
}
return $soap_result;
}
function UnWiki($s) {
return preg_replace(array("/\n+/", "/ /"), array("
", " "), $s);
}
function Untag($tag, $text) {
return preg_replace(array("/<\/?$tag>/"), array(""), $text);
}
function period($s) {
return $s == '' ? '' : ($s[strlen($s)-1] == '.' ? $s : "$s.");
}
function italic($s) {
return $s == '' ? '' : "$s";
}
// Browsing Nusoap's XML tree
/*
Important note about the format of parsed XML:
Nusoap uses a different representation depending on whether there
is only one subnode with a given name, or several.
1 subnode (e.g. one author in AuthorList):
- y -> Item = { !Name = x; ...; ! = y }
Several subnodes (e.g. multiple authors in AuthorList):
- y1
- y2 -> Item = [ { !Name = x1; ...; ! = y1 };
{ !Name = x2; ...; ! = y2 } ]
*/
function find_all_fields($field, $items) {
//$a = is_null($items['!']) ? $items : array($items);
$a = is_array($items) ? (array_key_exists('!',$items) ?
array($items) : $items) : array();
$result = array();
foreach ($a as $x) {
if (is_array($x)) {
if ($this->get($x,'!Name') == $field) {
if (array_key_exists('!',$x)) {
$result[] = $x['!'];
} else if (array_key_exists('Item',$x)) {
$result[] = $x['Item'];
}
}
}
};
return $result;
}
function find_field($field, $items) {
//$a = is_null($items['!']) ? $items : array($items);
$a = is_array($items) ? (array_key_exists('!',$items) ?
array($items) : $items) : array ();
foreach ($a as $x) {
if (is_array($x)) {
if ($x['!Name'] == $field) {
if (array_key_exists('!',$x)) {
return $x['!'];
} else if (array_key_exists('Item',$x)) {
return $x['Item'];
}
}
}
};
return "";
}
// Formatting of a PubMed or ISBNDB record
function FormatBib($authors, $title, $origin,
$pmid, $doi, $isbn, $isbndbref) {
$title = $this->period($title);
$title = $this->italic($title);
$authors = $this->period($authors);
$origin = $this->period($origin);
$codes = '';
if ($doi != '') $codes .= " doi:$doi";
if ($pmid != '') $codes .= " pmid:$pmid";
if ($isbn != '') $codes .= " isbn:$isbn";
$codes = $this->period($codes);
$result = "$authors $title $origin";
$style = 'class="extiw" style="color:Black; text-decoration:none"';
if ($doi != '') {
$title = 'title="View or buy article from publisher"';
$result = "$result";
} else if ($pmid != '') {
$title = 'title="View or buy article from publisher (if available)"';
$result =
"$result";
} else if ($isbn != '') {
$title = 'title="Book information at isbndb.org"';
$result = "$result";
}
return $result . $codes;
}
function ConcatAuthors($authors) {
$n = count($authors);
$result = "";
if ($n > 0) {
$result = $authors[0];
for ($i = 1; $i <= $n - 2; $i++) {
$result .= ", $authors[$i]";
}
if ($n == 2) {
$auth = $authors[$n-1];
$result .= " and $auth.";
} else if( $n > 2 ) {
$auth = $authors[$n-1];
$result .= ", and $auth.";
}
}
return $result;
}
// Queries to PubMed eSummary service
function FormatPubMed($pmdata) {
$result = array();
$docsum = $pmdata['DocSum'];
//$data = is_null($docsum['Item']) ? $docsum : array($docsum);
$data = array_key_exists('Item',$docsum) ? array($docsum) : $docsum;
foreach ($data as $entry) {
$pmid = $entry['Id'];
$items = $entry['Item'];
$authors =
$this->find_all_fields('Author',
$this->find_field('AuthorList',
$items));
$title = $this->find_field('Title', $items);
$source = $this->find_field('Source', $items);
$pubdate = $this->find_field('PubDate', $items);
$issue = $this->find_field('Issue', $items);
$volume = $this->find_field('Volume', $items);
$pages = $this->find_field('Pages', $items);
$doi = $this->find_field('DOI', $items);
$authors = $this->ConcatAuthors($authors);
$origin = "$source $pubdate";
$origin .= $volume == '' ? '' :
"; $volume" . ($issue == '' ? '' : "($issue)");
$origin .= $pages == '' ? '' : " $pages";
$result["$pmid"] = $this->FormatBib($authors, $title, $origin,
$pmid, $doi, '', '');
}
return $result;
}
function PubMedUrl($pmids) {
$list_uids = implode(",", $pmids);
return "http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?cmd=Retrieve&db=pubmed&dopt=Abstract&list_uids=$list_uids";
}
function HubMedUrl($pmids) {
$list_uids = implode(",", $pmids);
return "http://www.hubmed.org/display.cgi?uids=$list_uids";
}
// ISBNDB queries
function FormatAuthors($text) {
$patterns = array('/\s+([:,;.!?])/',
'/c(\d+)/',
'/[:,;!?]\s*$/m');
$replacements = array('\1',
'\1',
'.');
return preg_replace($patterns, $replacements, $text);
}
function FormatPublisher($text) {
$patterns = array('/\s+([:,;.!?])/',
'/c(\d+)/',
'/[:,;!?]\s*$/m');
$replacements = array('\1',
'\1',
'.');
return preg_replace($patterns, $replacements, $text);
}
function ar($a) { return is_array($a) ? $a : array(); }
function Biblio_isbndb_keys () {
global $isbndb_access_key, $isbndb_access_keys;
if (isset($isbndb_access_key))
return array($isbndb_access_key);
else if (isset($isbndb_access_keys))
return $isbndb_access_keys;
else
return array('9EOE2OGZ');
}
function pick ($a) {
return $a[rand(0,count($a)-1)];
}
function IsbnDbQuery_one($isbn) {
$access_key = $this->pick ($this->Biblio_isbndb_keys ());
$url = "http://isbndb.com/api/books.xml?access_key=${access_key}&index1=isbn&value1=${isbn}";
$text = $this->get_url($url);
$xml_parser = new Biblio_xml();
$data = $xml_parser->parse($text);
$thisbook =
$this->get($this->get($this->get(
$this->get($this->get($data, 0), 'child'), 0), 'child'), 0);
$isbndbref = $this->get($this->get($thisbook, 'attributes'), 'BOOK_ID');
$bookinfo = $this->ar($this->get($thisbook, 'child'));
$authors = '';
$title = '';
$origin = '';
foreach ($bookinfo as $field) {
switch ($this->get($field, 'name')) {
case 'TITLE':
$title = $this->get($field, 'content');
break;
case 'AUTHORSTEXT':
$authors = $this->FormatAuthors($this->get($field, 'content'));
break;
case 'PUBLISHERTEXT':
$origin = $this->FormatPublisher($this->get($field, 'content'));
break;
}
}
$result = $this->FormatBib($authors, $title, $origin,
'', '', $isbn, $isbndbref);
return $result;
}
function IsbnDbQuery($isbns) {
$result = array();
foreach ($isbns as $isbn) {
$result["$isbn"] = $this->IsbnDbQuery_one($isbn);
}
return $result;
}
// General formatting functions
function HtmlLink($url, $text) {
return "$text";
}
function HtmlInterLink($url, $text, $title) {
return "$text";
}
function HtmlExtLink($url, $text, $title) {
return "$text";
}
function noprint($s) {
return "$s";
}
function cleanLi($text) {
return trim(str_replace(array("\n", "\r"), " ", $text));
}
function parseBiblio($list) {
$result = array();
$pmids = array();
$isbns = array();
foreach ($list as $ref) {
$matches = array();
preg_match ('/([-+A-Za-z_0-9]+)(.*?)(?:[[:space:]]\/\/(.*))?$/s',
$ref, $matches);
$key = $this->get($matches,1);
$srctext = $this->cleanLi($this->get($matches,2));
$annot = $this->get($matches,3);
$m = array();
preg_match ('/^[[:space:]]*pmid=([0-9]+)/', $srctext, $m);
$pmid = $this->get($m,1);
preg_match ('/^[[:space:]]*isbn=([-0-9]+[Xx]?)/', $srctext, $m);
$isbn = $this->get($m,1);
if ($pmid != '') {
$result[] = array('key' => $key,
'annot' => $annot,
'pmid' => $pmid);
$pmids[] = $pmid;
} else if ($isbn != '') {
$result[] = array('key' => $key,
'annot' => $annot,
'isbn' => $isbn);
$isbns[] = $isbn;
} else { // free wikitext
$result[] = array('key' => $key,
'annot' => $annot,
'wikitext' => $srctext);
}
}
return array('entries' => $result,
'pmids' => $pmids,
'isbns' => $isbns);
}
// Parse wikitext
function parse_freetext ($parser, $wikitext) {
$localParser = new Parser();
$parserResult =
$localParser->parse($wikitext, $parser->getTitle(), $parser->getOptions(), false);
return trim($parserResult->getText());
}
function format_annot ($s) {
// Any suggestion is appreciated
return "
";
}
function parse_annot ($parser, $wikitext) {
$text = trim ($wikitext);
$result = $text == '' ? '' :
$this->format_annot($this->parse_freetext ($parser, $text));
return $result;
}
// Conversion of the contents of tags
function render_cite($input, $parser) {
$keys = preg_split('/[^-+A-Za-z_0-9]+/', $input, -1, PREG_SPLIT_NO_EMPTY);
$list = array();
foreach ($keys as $key) {
$index = $this->CitationIndex($key);
$list[] = array($index,$key);
}
sort($list);
$links = array();
foreach ($list as $ent) {
$link = $this->HtmlLink("#bibkey_$ent[1]", $ent[0]+1);
$links[] = $link;
}
return "[". implode(", ", $links) ."]";
}
// Conversion of the contents of tags
function render_biblio($input, $parser) {
global $Biblio;
$refs = array();
$list = preg_split("/[[:space:]]*^[ \t]*#[[:space:]]*/m",
$input, -1, PREG_SPLIT_NO_EMPTY);
$parseResult = $this->parseBiblio($list);
$entries = $parseResult['entries'];
$pmids = $parseResult['pmids'];
$isbns = $parseResult['isbns'];
$pmdata = $this->eSummary($pmids);
$pmentries = $this->FormatPubMed($pmdata);
$isbnentries = $this->IsbnDbQuery($isbns);
$refs = array();
foreach ($entries as $ref) {
$key = $this->get($ref, 'key');
$annot = $this->parse_annot($parser, $this->get($ref, 'annot'));
$pmid = $this->get($ref, 'pmid');
$isbn = $this->get($ref, 'isbn');
$wikitext = $this->get($ref, 'wikitext');
$text = '';
if (!is_null($pmid)) { // PubMed result
$pmlink = $this->HtmlInterLink($this->PubMedUrl(array($pmid)),
"PubMed", "PMID $pmid");
$hmlink = $this->HtmlInterLink($this->HubMedUrl(array($pmid)),
"HubMed", "PMID $pmid");
$text = $pmentries["$pmid"] . $this->noprint(" $pmlink $hmlink");
} else if (!is_null($isbn)) { // ISBN
$text = $isbnentries["$isbn"];
} else if (!is_null($wikitext)) { // plain wikitext
$text = $this->parse_freetext($parser, $wikitext);
}
$index = $this->CitationIndex($key);
$refs[] = array('index' => $index,
'key' => $key,
'text' => $text,
'pmid' => $pmid,
'isbn' => $isbn,
'annot' => $annot);
}
sort($refs); reset($refs);
$sorted_pmids = array ();
foreach ($refs as $ref) {
$pmid = $this->get($ref,'pmid');
if (!is_null($pmid)) { $sorted_pmids[] = $pmid; }
}
$header = "";
$footer = "";
if (count($sorted_pmids) > 0) {
$footer .= 'All Medline abstracts: ' .
$this->HtmlInterLink($this->PubMedUrl($sorted_pmids),
"PubMed", "All abstracts at PubMed") . " " .
$this->HtmlInterLink($this->HubMedUrl($sorted_pmids),
"HubMed", "All abstracts at HubMed");
$footer = $this->noprint($footer);
}
$result = array();
foreach ($refs as $ref) {
$index = $this->get($ref, 'index') + 1;
$key = $this->get($ref, 'key');
$annot = $this->get($ref, 'annot');
$text = $this->get($ref, 'text');
$vkey = $this->noprint("[$key]");
$vkey .= " $annot";
$result[] =
" $text $vkey\n";
}
//error_reporting($initial_error_reporting);
$version = $this->BiblioVersion;
return $header . "" .
'' . implode ("", $result) . '
' . $footer;
}
}
$Biblio = new Biblio;
// Conversion of the contents of tags
function Biblio_render_cite($input, $params, &$parser) {
global $Biblio;
return $Biblio->render_cite($input, $parser);
}
// Conversion of the contents of tags
function Biblio_render_biblio($input, $params, &$parser) {
global $Biblio;
return $Biblio->render_biblio($input, $parser);
}
?>