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 "
$s
"; } 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); } ?>