'%first_author%. %iso%.
%pmid_url% %pmcid_url% %doi_url%',
"long" => '%authors%. %title%. %iso%.
%pmid_url% %pmcid_url% %doi_url%',
"long_tt" => '%authors%. %title_tt%. %iso%.
%pmid_url% %pmcid_url% %doi_url%',
"long_pdf" => '%authors%. %title%. %iso%.
%pmid_url% %pmcid_url% %doi_url% %localpdf% %tweet%',
"long_tt_pdf" => '%authors%. %title_tt%. %iso%.
%pmid_url% %pmcid_url% %doi_url% %localpdf% %tweet%',
"long_abstract" => '%authors%. %title%. %iso%.
%pmid_url% %pmcid_url% %doi_url% %abstract% %abstractFr% %tweet%',
"long_tt_abstract" => '%authors%. %title_tt%. %iso%.
%pmid_url% %pmcid_url% %doi_url% %abstract% %abstractFr% %tweet%',
"long_abstract_pdf" => '%authors%. %title%. %iso%.
%pmid_url% %pmcid_url% %doi_url% %abstract% %abstractFr% %localpdf%',
"long_tt_abstract_pdf" => '%authors%. %title_tt%. %iso%.
%pmid_url% %pmcid_url% %doi_url% %abstract% %abstractFr% %localpdf%',
"vancouver" => '%vancouver%',
"vancouver_links" => '%vancouver%
%pmid_url% %pmcid_url%',
"npg" => '%authorsLimit3% %title_tt%. %npg_iso%.',
"npg_full" => '%npg_full%',
"npg_full_links" => '%npg_full% %pmid_url% %pmcid_url%',
"gpnv_full" => '%gpnv_full%',
// Add item one by one
"authors" => '%authors%',
"title" => '%title%',
"year" => '%year%',
"date" => '%month% %year%',
"journal" => '%journal_title%',
"journaliso" => '%journal_iso%',
"doi_link" => '%doi% %journal_url%',
"abstract_wiki" => '%abstract_wiki%',
"abstract_html" => '%abstract_html%',
"listgroup" => '%listgroup%'
);
var $commands = Array(
'addtt',
'addhash_fr',
'convertid',
'test',
'raw_medline',
'clear_raw_medline',
'remove_dir',
'search',
'recreate_cross_refs',
'full_pdf_list',
);
// Constructor
public function __construct(){
if (!class_exists('pubmed2020_cache'))
@require_once(DOKU_PLUGIN.'pubmed2020/classes/cache.php');
if (!class_exists('PubMed2020'))
@require_once(DOKU_PLUGIN.'pubmed2020/classes/pubmed2020.php');
$this->pubmed2020 = new PubMed2020();
$this->pubmedCache = new pubmed2020_cache("pubmed","pubmed","nbib");
$this->documentFormat = $this->getConf('default_command');
$this->useDocumentFormat = false;
}
function getType() { return 'substition'; }
function getSort() { return 306; }
/**
* Plugin tag format: {{pmid>command:arg}}
*/
function connectTo($mode) {
$this->Lexer->addSpecialPattern('\{\{(?:pmid|pmcid)>[^}]*\}\}',
$mode,'plugin_pubmed2020');
}
/**
* Handle the match.
*/
function handle($match, $state, $pos, Doku_Handler $handler){
$match = str_replace("{{", "", $match);
$match = str_replace("}}", "", $match);
return array($state, explode('>', $match, 2));
}
function _span($refs, $class, $id) {
// No data
if (empty($refs[$id]))
return "";
// Data = array
if (is_array($refs[$id]))
return "".hsc(implode(", ",$refs[$id]))."";
// Default
return "".hsc($refs[$id])."";
}
function _a($refs, $class, $href, $id, $text) {
// No data
if (empty($refs[$id]))
return "";
// Default
return "[$text]";
}
/**
* Replace tokens in the string \e $outputString using the array $refs.
* \returns Replaced string content.
*/
function replaceTokens($outputString, $refs) {
// Empty array -> exit
if (count($refs) < 2) { // PMID is always included
return sprintf($this->getLang('pubmed_not_found'), $refs["pmid"]);
}
// $r = replacement key/value: key=tag to replace in string, value=replacement string
$r = array(
// IDs
"pmid" => "",
"pmcid" => "",
"doi" => "",
// AUTHORS
"authors" => $this->_span($refs, "authors", "authors"),
"authorsLimit3" => $this->_span($refs, "authors", "authorsLimit3"),
"first_author" => $this->_span($refs, "authors", "first_author"),
"authorsVancouver" => $this->_span($refs, "vancouver authors", "authorsVancouver"),
"collectif" => $this->_span($refs, "authors", "collectif"),
"corporate_author"=> $this->_span($refs, "authors", "corporate_author"),
// CITATION
"vancouver" => "",
"npg_iso" => $this->_span($refs, "iso", "npg_iso"),
"npg_full" => $this->_span($refs, "npg", "npg_full"),
"gpnv_full" => $this->_span($refs, "gpnv_authors", "gpnv_full_authors").
$this->_span($refs, "gpnv_title", "gpnv_full_title").
$this->_span($refs, "gpnv_journal", "gpnv_full_journal").
$this->_span($refs, "gpnv_iso", "gpnv_full_iso")
,
// URLS
"pmid_url" => $this->_a($refs, "pmid", $refs["url"],
"url", "PMID: ".$refs["pmid"]),
"pmcid_url" => $this->_a($refs, "pmcid", $refs["pmcurl"],
"pmcid", "PMCID: ".$refs["pmcid"]),
"pmc_url" => $this->_a($refs, "pmcid", $refs["pmcurl"],
"pmcid", "PMCID: ".$refs["pmcid"]),
"doi_url" => $this->_a($refs, "pmcid", $this->doiUrl.$refs["doi"],
"doi", "DOI: ".$refs["doi"]),
"journal_url" => $this->_a($refs, "pmid", $this->doiUrl.$refs["doi"],
"pmid", $refs["iso"]),
"tweet_current" => "Twitter cet article ".
"(lien vers ce site)",
"tweet_pmid" => "".
"Twitter cet article (lien vers l'article)",
// TITLE
"title" => "",
"booktitle" => $this->_span($refs, "title", "booktitle"),
"title_low" => "",
"translated_title" => $this->_span($refs, "title", "translated_title"),
"translated_title_low" => $this->_span($refs, "title", "translated_title_low"),
"title_tt" => $this->_span($refs, "title", "translated_title"),
// JOURNAL
"journal_iso" => "",
"journal_title" => "",
"journal_iso" => "",
// OTHERS
"lang" => "",
"iso" => "",
"vol" => "",
"issue" => "",
"year" => "",
"month" => "",
"pages" => "",
"abstract" => '
'.$refs["abstract_html"].'',
"abstract_wiki" => $refs["abstract_wiki"],
"abstract_html" => $refs["abstract_html"],
"type" => "",
"country" => "",
"copyright" => "",
"collection_title" => "",
"publisher" => "",
);
$r["tweet"] = "
";
// Check if we have the local PDF of the paper
$localPdf = $this->pubmedCache->GetLocalPdfPath($refs["pmid"], $refs["doi"]);
if (empty($localPdf)) {
$r["localpdf"] = $this->_span($refs, "nopdf", "No PDF");
} else {
$r["localpdf"] = $this->_a($refs, "localPdf", $localPdf, "pmid", "PDF");
}
foreach($r as $key => $value) {
$v = $value;
if (empty($v))
$v = $this->_span($refs, $key, $key);
$outputString = str_replace("%".$key."%", $v, $outputString);
}
// note tt -> if empty = title
// note doi & journal_url -> if empty add nothing
//echo print_r($r);
$refs["abstractFr"] = $this->pubmedCache->GetTranslatedAbstract($refs["pmid"]);
if (empty($refs["abstractFr"])) {
$outputString = str_replace("%abstractFr%", '', $outputString);
} else {
// TODO: Create a form to send french abstrat to this class
// TODO: Allow to store it in a separate file abstractfr_{pmid}.txt
$outputString = str_replace("%abstractFr%", ''.$refs["abstractFr"].'', $outputString);
}
// Bootstrap listgroup
if (strpos($outputString, "%listgroup%") !== false) {
if (empty($refs["translated_title"])) {
$lg = "";
$lg .= "
";
$lg .= "- ";
$lg .= "".$refs["title"]."
";
} else {
$lg = "";
$lg .= "
";
$lg .= "- ";
$lg .= "".$refs["translated_title"]."
";
$lg .= "- ";
$lg .= " ";
$lg .= $refs["title"]."
";
}
$lg .= "- ";
$lg .= " ";
$lg .= " ";
$lg .= implode(', ',$refs["authors"]);
$lg .= "
";
$lg .= "- ";
$lg .= " ";
$lg .= " ".$refs["journal_title"]."
";
$lg .= "- ";
$lg .= " ";
$lg .= "".$refs["year"]." ".$refs["month"]."
";
$lg .= "- ";
$lg .= " ";
$lg .= "".$refs["iso"]."
";
// Keywords
$lg .= "- ";
$lg .= " ";
if (!empty($refs["mesh"])) {
$lg .= "".implode(', ',$refs["mesh"])." ";
} else if (!empty($refs["keywords"])) {
$lg .= "".implode(', ',$refs["keywords"])."";
} else {
$lg .= "Aucun mots clés";
}
$lg .= "
";
// User added HASHTAGS
if (!empty($refs["hashtags"])) {
$lg .= "- ";
$lg .= " ";
$lg .= "".$refs["hashtags"]."
";
}
// Links
$lg .= "- ";
$lg .= "Liens
";
$lg .= "- ";
$lg .= " ";
$lg .= " Traduction automatique en Français sur Google Translate
";
$lg .= "- ";
$lg .= " ";
$lg .= " DOI: ".$refs["doi"]."
";
$lg .= "- ";
$lg .= " ";
$lg .= " PMID: ".$refs["pmid"]."
";
if (!empty($refs["similarurl"])) {
$lg .= "- ";
$lg .= " ";
$lg .= " Articles similaires
";
}
if (!empty($refs["citedbyurl"])) {
$lg .= "- ";
$lg .= " ";
$lg .= " Cité par
";
}
if (!empty($refs["referencesurl"])) {
$lg .= "- ";
$lg .= " ";
$lg .= " Références
";
}
if (!empty($refs["pmcid"])) {
$lg .= "- ";
$lg .= " ";
$lg .= " Texte complet gratuit
";
}
// Twitter
$lg .= "- ";
$lg .= "Twitter
";
$lg .= "- ";
$lg .= " ";
$lg .= " Twitter cet article (lien vers l'article)
";
$lg .= "- ";
$lg .= " ";
$lg .= " Twitter cet article (lien vers cette page)
";
$lg .= "
";
$lg .= "
";
$outputString = str_replace("%listgroup%", $lg, hsc($outputString));
}
// Remove double points separated with a span tag
$outputString = str_replace("..", '.', $outputString);
return $outputString;
}
/**
* Create output
* We have different database to extract data
* "pmid" = pubmed
* "pmcid" = pmc
*/
function render($mode, Doku_Renderer $renderer, $data) {
if ($mode != 'xhtml')
return false;
// Get the command and its arg(s)
list($state, $query) = $data;
list($base, $req) = $query;
list($cmd, $id) = explode(':', $req, 2);
$cmd = strtolower($cmd);
// If command is empty (in this case, command is the numeric pmids)
// Catch default command in plugin's preferences
$regex = '/^[0-9,]+$/';
// if (preg_match($regex, $cmd) === 1) {
if (empty($id)) {
$id = $cmd;
$cmd = $this->documentFormat;
}
// Manage the article reference commands in :
// short, long, long_abstract, vancouver,
// or user
$this->outputTpl["user"] = $this->getConf('user_defined_output');
// Allow user to define a document format
if ($cmd === "doc_format") {
$this->documentFormat = $id;
$this->useDocumentFormat = true;
return true;
} else if ($this->useDocumentFormat && (!in_array($cmd, $this->commands))) {
$cmd = $this->documentFormat;
}
//echo $cmd.PHP_EOL;
if (array_key_exists($cmd, $this->outputTpl)) {
// Check and open multiple PMIDs
$multipleIds = strpos($id, ",");
if ($multipleIds) {
$renderer->doc .= "";
}
$id = explode(",", $id);
// With multiple PMIDs, the first one can be a word
if ($id[0] === "sort") {
// Remove [0]
array_shift($id);
// Sort ids
sort($id);
$id = array_reverse($id);
}
// Remove duplicates
$id = array_unique($id, SORT_REGULAR);
// Add each PMID to the renderer
foreach ($id as $curId) {
$renderer->doc .= $this->getIdOutput($cmd, $base, $curId, $multipleIds);
}
// Close multiple PMIDs
if ($multipleIds) {
$renderer->doc .= "
";
}
} else {
// Manage all other commands
switch($cmd) {
case 'addtt': // Ok PubMed2020
// $id = pmid|translatedTitle
list($id, $tt) = explode('|', $id, 2);
$raw = $this->getMedlineContent($base, $id);
if (strpos($raw, "TT - ") === false) {
$raw .= "\nTT - ".$tt."\n";
} else {
// Check raw value
$pattern = "/TT - ".$tt."/";
if (!preg_match($pattern, $raw)) {
$pattern = "/TT - .*/";
$raw = preg_replace($pattern, "\nTT - ".$tt."\n", $raw);
}
}
$this->pubmedCache->saveRawMedlineContent($base, $raw);
return true;
case 'addhash_fr': // Ok PubMed2020
// $id = pmid|hash1,hash2,hash3
list($id, $hash) = explode('|', $id, 2);
$raw = $this->getMedlineContent($base, $id);
if (strpos($raw, "HASH- ") === false) {
$raw .= "\nHASH- ".$hash."\n";
} else {
// Check raw value
$pattern = "/HASH- ".$hash."/";
if (!preg_match($pattern, $raw)) {
$pattern = "/HASH- .*/";
$raw = preg_replace($pattern, "\nHASH- ".$hash."\n", $raw);
}
}
$this->pubmedCache->saveRawMedlineContent($base, $raw);
return true;
case 'convertid': // Ok PubMed2020
$r = $this->pubmed2020->convertId($id);
if ($r) {
$renderer->doc .= "PMID: ".$r->pmid." ; DOI: ".$r->doi." ; PMC: ".$r->pmcid;
} else {
$renderer->doc .= "Id not found: ".$id;
}
return true;
case 'test': // Ok PubMed2020
$this->runTests();
return true;
case 'raw_medline': // Ok PubMed2020
// Check multiple PMIDs (PMIDs can be passed in a coma separated list)
$multipleIds = strpos($id, ",");
$id = explode(",", $id);
foreach ($id as $curId) {
if (!is_numeric($curId)){
$renderer->doc .= sprintf($this->getLang('pubmed_wrong_format'));
return false;
}
$raw = $this->getMedlineContent($base, $curId);
if (empty($raw)) {
$renderer->doc .= sprintf($this->getLang('pubmed_not_found'), $curId);
return false;
}
$renderer->doc .= "
".htmlspecialchars($raw, ENT_QUOTES)."
";
} // Foreach PMIDs
return true;
case 'clear_raw_medline':
$this->pubmedCache->clearCache();
$renderer->doc .= 'Cleared.';
return true;
case 'remove_dir':
$this->pubmedCache->removeDir();
$renderer->doc .= 'Directory cleared.';
return true;
case 'search':
$link = $this->pubmed2020->getPubmedSearchURL($id);
$renderer->doc .='
';
$renderer->doc .= ''.$link[0].'';
$renderer->doc .='';
return true;
case 'recreate_cross_refs':
$this->pubmedCache->recreateCrossRefFile();
return true;
case 'full_pdf_list':
// Get all PMID from cache
$mediaList = array_keys($this->pubmedCache->getAllMediaPaths());
// Get all PMID using the local PDF filename
$pdfPmids = $this->pubmedCache->GetAllAvailableLocalPdfByPMIDs();
// Remove all local PDF PMIDs already in the media list
$pdfPmids = array_diff($pdfPmids, $mediaList);
// Remove all pdfPmid if present in the mediaList
$pdfDois = $this->pubmedCache->GetAllAvailableLocalPdfByDOIs();
// Get PMIDs from DOIs
$pmids = $this->pubmedCache->PmidFromDoi($pdfDois);
// $i = 0;
foreach($pdfDois as $doi) {
// if (++$i == 5)
// break;
$raw = $this->pubmed2020->getDataFromCtxp($base, "", $doi);
if (!empty($raw)) {
$this->pubmedCache->saveRawMedlineContent($base, $raw);
}
}
// Create a complete list of PMIDs to show
//$fullPmids = array_merge($pdfPmids, $pmids, $mediaList);
$fullPmids = array_merge($pdfPmids, $pmids);
// Check multiple PMIDs (PMIDs can be passed in a coma separated list)
$renderer->doc .= "
";
foreach($fullPmids as $currentPmid) {
$renderer->doc .= $this->getIdOutput("long_abstract", $base, $currentPmid, true);
} // Foreach PMIDs
foreach($pdfDois as $doi) {
$renderer->doc .=
"";
} // Foreach PMIDs
$renderer->doc .= "
";
return true;
default: // Ok PubMed2020
// Command was not found..
$renderer->doc .= '
';
$renderer->doc .= sprintf($this->getLang('plugin_cmd_not_found'),$cmd);
$renderer->doc .= '
';
$renderer->doc .= '
';
$renderer->doc .= $this->getLang('pubmed_available_cmd');
$renderer->doc .= '
';
return true;
}
}
}
/**
* Get Medline raw data from cache or get it from NCBI
*/
function getMedlineContent($base, $id) {
global $conf;
$cached = $this->pubmedCache->getMedlineContent($base, $id);
if ($cached !== false) {
return $cached;
}
// Get content from PubMed website
$raw = $this->pubmed2020->getDataFromCtxp($base, $id);
// Save to cache
$this->pubmedCache->saveRawMedlineContent($base, $raw);
return $raw;
}
/**
* Check PMID format
*/
function checkIdFormat($base, $id) {
// Check PMID/PMCID format (numeric, 7 or 8 length)
if (!is_numeric($id) || (strlen($id) < 6 || strlen($id) > 8)) {
return false;
}
return true;
} // Ok pubmed2020
/**
* Get pubmed string output according to the given unique
* ID code passed and the command.
* $multipleIds : boolean, use it if the output in inside a multiple ids request
*/
function getIdOutput($cmd, $base, $id, $multipleIds) {
if (!$this->checkIdFormat($base, $id)) {
return sprintf($this->getLang('pubmed_wrong_format'));
}
// Get article content (from cache or web)
$raw = $this->getMedlineContent($base, $id);
if (empty($raw)) {
return sprintf($this->getLang('pubmed_not_found'), $id);
return false;
}
// Get the abstract of the article
$refs = $this->pubmed2020->readMedlineContent($raw, $this);
// Catch updated user output template
$outputTpl['user'] = $this->getConf('user_defined_output');
// Construct reference to article (author.title.rev.year..) according to command
$output = "";
if ($multipleIds)
$output .= "
";
if (empty($this->outputTpl[$cmd]))
$cmd = "long_abstract";
// $cmd contains abstract -> use div instead of span
$block = "span";
if (strpos($cmd, 'abstract') !== false) {
$block = "div";
}
$output .= "<{$block} class=\"pubmed\"><{$block} class=\"{$cmd}\"";
if ($multipleIds)
$output .= ' style="margin-bottom:1em"';
$output .= ">";
$output .= $this->replaceTokens($this->outputTpl[$cmd], $refs);
$output .= "{$block}>{$block}>";
if ($multipleIds)
$output .= "";
return $output;
} // Ok pubmed2020
/**
* Create a link to Tweet the paper
* - $refs is the full paper references (use pubmed2020 class to get it)
* - $currentUrl if true tweet with current website URL, if false use the $refs["url"]
*/
function _createTwitterUrl($refs, $currentUrl = false) {
// https://developer.twitter.com/en/docs/twitter-for-websites/tweet-button/guides/web-intent
// 280 characters when text is combined with any passed hashtags, via, or url parameters.
// HASHTAGS
if (!empty($refs["hashtags"])) {
$list = explode(",", $refs["hashtags"]);
foreach ($list as &$value) {
$value = trim($value);
$value = str_replace(" ", "_", $value);
$value = str_replace("-", "ー", $value);
}
$hash = "&hashtags=".implode(",", $list); // Comma separated without #
} else {
$hash = "";
}
// TEXT
if (!empty($refs["translated_title"])) {
$txt = $refs["translated_title"]."\n\n";
} else {
$txt = $refs["title"]."\n\n";
}
$txt .= $refs["journal_iso"]." ".$refs["year"]."\n";
$txt = "&text=".rawurlencode($txt);
// URL
$url = "";
// Get current page URL
if ($currentUrl) {
// Use Twitter URL shorteners
// See
// $conf['twitter_url_shortener_format_pmid'] = "";
// $conf['twitter_url_shortener_format_pmcid'] = "";
if (!empty($this->getConf('twitter_url_shortener_format_pmid'))
&& !empty($refs["pmid"])) {
$url = $this->getConf('twitter_url_shortener_format_pmid');
$url = str_replace("%PMID%", $refs["pmid"], $url);
} else if (!empty($this->getConf('twitter_url_shortener_format_pcmid'))
&& !empty($refs["pmid"])) {
$url = $this->getConf('twitter_url_shortener_format_pmcid');
$url = str_replace("%PMCID%", $refs["pmcid"], $url);
} else {
global $ID;
$url = wl($ID,'',true);
}
} else {
$url = $refs["url"];
}
$url = "&url=".rawurlencode($url);
// VIA
if (!empty($this->getConf('twitter_via_user_name'))) {
$via = "&via=".$this->getConf('twitter_via_user_name');
}
//$related = "&related=";
// Create full link
$tweet = "";
$tweet .= str_replace(array("-", "#"), "", $hash);
$tweet .= $txt;
$tweet .= $url;
$tweet .= $via;
$tweet = substr($tweet, 1);
$tweet = sprintf($this->twitterUrl, $tweet);
return $tweet;
}
/**
* Only for dev usage
*
* Tests: 25617070 for author "de la Cruz M"
*/
function runTests() {
echo "Starting PubMed2020 Tests
";
// Test CTXP URLs
$retrieved = $this->pubmed2020->getDataFromCtxp("pmid", "15924077", "doi");
// Test MedLine Format Reader
$myfile = fopen(DOKU_PLUGIN.'pubmed/tests/PM15924077.nbib', "r") or die("Unable to open file!");
$s = fread($myfile, filesize(DOKU_PLUGIN.'pubmed/tests/PM15924077.nbib'));
fclose($myfile);
// Check retrieved files
if ($retrieved === $s)
echo "File Content: Ok".PHP_EOL;
else
echo "File Content: NOT Ok".PHP_EOL;
$this->pubmed2020->readMedlineContent($s, "PMID", $this);
}
}
?>