1<?php
2/*
3description : Dokuwiki PubMed2020 plugin
4author      : Eric Maeker
5email       : eric.maeker[at]gmail.com
6lastupdate  : 2020-12-27
7license     : Public-Domain
8*/
9
10/**
11 * Add crossref eg: https://api.crossref.org/works/10.1016/j.npg.2020.12.002
12 */
13
14if(!defined('DOKU_INC')) die();
15if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
16require_once(DOKU_PLUGIN.'syntax.php');
17
18class syntax_plugin_pubmed2020 extends DokuWiki_Syntax_Plugin {
19  var $documentFormat;
20  var $useDocumentFormat;
21  var $pubmed2020;
22  var $pubmedCache;
23  var $doiUrl = 'http://dx.doi.org/'; //+doi
24  var $pmcUrl = 'https://www.ncbi.nlm.nih.gov/pmc/articles/%s/pdf'; //+pmc
25  var $twitterUrl = 'https://twitter.com/intent/tweet?%s';
26  var $outputTpl = array(
27      "short" => '%first_author%. %iso%.<br/>%pmid_url% %pmcid_url% %doi_url%',
28      "long" => '%authors%. %title%. %iso%.<br/>%pmid_url% %pmcid_url% %doi_url%',
29      "long_tt" => '%authors%. %title_tt%. %iso%.<br/>%pmid_url% %pmcid_url% %doi_url%',
30      "long_pdf" => '%authors%. %title%. %iso%.<br/>%pmid_url% %pmcid_url% %doi_url% %localpdf% %tweet%',
31      "long_tt_pdf" => '%authors%. %title_tt%. %iso%.<br/>%pmid_url% %pmcid_url% %doi_url% %localpdf% %tweet%',
32      "long_abstract" => '%authors%. %title%. %iso%.<br/>%pmid_url% %pmcid_url% %doi_url% %abstract% %abstractFr% %tweet%',
33      "long_tt_abstract" => '%authors%. %title_tt%. %iso%.<br/>%pmid_url% %pmcid_url% %doi_url% %abstract% %abstractFr% %tweet%',
34      "long_abstract_pdf" => '%authors%. %title%. %iso%.<br/>%pmid_url% %pmcid_url% %doi_url% %abstract% %abstractFr% %localpdf%',
35      "long_tt_abstract_pdf" => '%authors%. %title_tt%. %iso%.<br/>%pmid_url% %pmcid_url% %doi_url% %abstract% %abstractFr% %localpdf%',
36      "vancouver" => '%vancouver%',
37      "vancouver_links" => '%vancouver%<br/>%pmid_url% %pmcid_url%',
38      "npg" => '%authorsLimit3% %title_tt%. %npg_iso%.',
39      "npg_full" => '%npg_full%',
40      "npg_full_links" => '%npg_full% %pmid_url% %pmcid_url%',
41      "gpnv_full" => '%gpnv_full%',
42      // Add item one by one
43      "authors" => '%authors%',
44      "title" => '%title%',
45      "year" => '%year%',
46      "date" => '%month% %year%',
47      "journal" => '%journal_title%',
48      "journaliso" => '%journal_iso%',
49      "doi_link" => '%doi% %journal_url%',
50      "abstract_wiki" => '%abstract_wiki%',
51      "abstract_html" => '%abstract_html%',
52      "listgroup" => '%listgroup%'
53      );
54  var $commands = Array(
55    'addtt',
56    'addhash_fr',
57    'convertid',
58    'test',
59    'raw_medline',
60    'clear_raw_medline',
61    'remove_dir',
62    'search',
63    'recreate_cross_refs',
64    'full_pdf_list',
65  );
66
67  // Constructor
68  public function __construct(){
69    if (!class_exists('pubmed2020_cache'))
70      @require_once(DOKU_PLUGIN.'pubmed2020/classes/cache.php');
71    if (!class_exists('PubMed2020'))
72      @require_once(DOKU_PLUGIN.'pubmed2020/classes/pubmed2020.php');
73    $this->pubmed2020  = new PubMed2020();
74    $this->pubmedCache = new pubmed2020_cache("pubmed","pubmed","nbib");
75    $this->documentFormat = $this->getConf('default_command');
76    $this->useDocumentFormat = false;
77  }
78
79  function getType() { return 'substition'; }
80  function getSort() { return 306; }
81
82  /**
83   * Plugin tag format: {{pmid>command:arg}}
84   */
85  function connectTo($mode) {
86    $this->Lexer->addSpecialPattern('\{\{(?:pmid|pmcid)>[^}]*\}\}',
87                                    $mode,'plugin_pubmed2020');
88  }
89
90 /**
91  * Handle the match.
92  */
93  function handle($match, $state, $pos, Doku_Handler $handler){
94    $match = str_replace("{{", "", $match);
95    $match = str_replace("}}", "", $match);
96    return array($state, explode('>', $match, 2));
97  }
98
99
100  function _span($refs, $class, $id) {
101    // No data
102    if (empty($refs[$id]))
103      return "";
104    // Data = array
105    if (is_array($refs[$id]))
106      return "<span class=\"$class\">".hsc(implode(", ",$refs[$id]))."</span>";
107    // Default
108    return "<span class=\"$class\">".hsc($refs[$id])."</span>";
109  }
110
111  function _a($refs, $class, $href, $id, $text) {
112    // No data
113    if (empty($refs[$id]))
114      return "";
115    // Default
116    return "[<a class=\"$class\" href=\"$href\" ".
117           "rel=\"noopener\" target=\"_blank\" ".
118           "title=\"$text\" ".
119           ">$text</a>]";
120  }
121
122  /**
123   * Replace tokens in the string \e $outputString using the array $refs.
124   * \returns Replaced string content.
125   */
126  function replaceTokens($outputString, $refs) {
127      // Empty array -> exit
128      if (count($refs) < 2) { // PMID is always included
129        return sprintf($this->getLang('pubmed_not_found'), $refs["pmid"]);
130      }
131      // $r = replacement key/value: key=tag to replace in string, value=replacement string
132      $r = array(
133         // IDs
134        "pmid"          => "",
135        "pmcid"         => "",
136        "doi"           => "",
137
138        // AUTHORS
139        "authors"       => $this->_span($refs, "authors", "authors"),
140        "authorsLimit3" => $this->_span($refs, "authors", "authorsLimit3"),
141        "first_author"  => $this->_span($refs, "authors", "first_author"),
142        "authorsVancouver" => $this->_span($refs, "vancouver authors", "authorsVancouver"),
143        "collectif"     => $this->_span($refs, "authors", "collectif"),
144        "corporate_author"=> $this->_span($refs, "authors", "corporate_author"),
145
146        // CITATION
147        "vancouver"     => "",
148
149        "npg_iso"       => $this->_span($refs, "iso", "npg_iso"),
150        "npg_full"      => $this->_span($refs, "npg", "npg_full"),
151
152        "gpnv_full"      => $this->_span($refs, "gpnv_authors", "gpnv_full_authors").
153                            $this->_span($refs, "gpnv_title", "gpnv_full_title").
154                            $this->_span($refs, "gpnv_journal", "gpnv_full_journal").
155                            $this->_span($refs, "gpnv_iso", "gpnv_full_iso")
156                            ,
157
158        // URLS
159        "pmid_url"      => $this->_a($refs, "pmid", $refs["url"],
160                                      "url", "PMID: ".$refs["pmid"]),
161        "pmcid_url"     => $this->_a($refs, "pmcid", $refs["pmcurl"],
162                                     "pmcid", "PMCID: ".$refs["pmcid"]),
163        "pmc_url"       => $this->_a($refs, "pmcid", $refs["pmcurl"],
164                                     "pmcid", "PMCID: ".$refs["pmcid"]),
165        "doi_url"       => $this->_a($refs, "pmcid", $this->doiUrl.$refs["doi"],
166                                      "doi", "DOI: ".$refs["doi"]),
167        "journal_url"   => $this->_a($refs, "pmid", $this->doiUrl.$refs["doi"],
168                                      "pmid", $refs["iso"]),
169
170        "tweet_current" => "<a href='".$this->_createTwitterUrl($refs, true).
171                             "' rel='noopener' target='_blank''>Twitter cet article ".
172                             "(lien vers ce site)</a>",
173        "tweet_pmid"    => "<a href='".$this->_createTwitterUrl($refs).
174                             "' rel='noopener' target='_blank''>".
175                             "Twitter cet article (lien vers l'article)</a>",
176
177        // TITLE
178        "title"         => "",
179        "booktitle"     => $this->_span($refs, "title", "booktitle"),
180        "title_low"     => "",
181        "translated_title" => $this->_span($refs, "title", "translated_title"),
182        "translated_title_low" => $this->_span($refs, "title", "translated_title_low"),
183        "title_tt"      => $this->_span($refs, "title", "translated_title"),
184
185        // JOURNAL
186        "journal_iso"   => "",
187        "journal_title" => "",
188        "journal_iso"   => "",
189
190        // OTHERS
191        "lang"          => "",
192        "iso"           => "",
193        "vol"           => "",
194        "issue"         => "",
195        "year"          => "",
196        "month"         => "",
197        "pages"         => "",
198        "abstract"      => '<br/><span class="abstract">'.$refs["abstract_html"].'</span>',
199        "abstract_wiki" => $refs["abstract_wiki"],
200        "abstract_html" => $refs["abstract_html"],
201        "type"          => "",
202        "country"       => "",
203        "copyright"     => "",
204        "collection_title" => "",
205        "publisher"     => "",
206    );
207    $r["tweet"] = "<div class='pubmed tweetme'>".
208                  $r["tweet_pmid"]."<br/>".
209                  $r["tweet_current"].
210                  "</div>";
211    // Check if we have the local PDF of the paper
212    $localPdf = $this->pubmedCache->GetLocalPdfPath($refs["pmid"], $refs["doi"]);
213    if (empty($localPdf)) {
214      $r["localpdf"] = $this->_span($refs, "nopdf", "No PDF");
215    } else {
216      $r["localpdf"] = $this->_a($refs, "localPdf", $localPdf, "pmid", "PDF");
217    }
218
219    foreach($r as $key => $value) {
220      $v = $value;
221      if (empty($v))
222        $v = $this->_span($refs, $key, $key);
223      $outputString = str_replace("%".$key."%", $v, $outputString);
224    }
225
226      // note tt -> if empty = title
227      // note doi & journal_url -> if empty add nothing
228      //echo print_r($r);
229
230      $refs["abstractFr"] = $this->pubmedCache->GetTranslatedAbstract($refs["pmid"]);
231      if (empty($refs["abstractFr"])) {
232        $outputString = str_replace("%abstractFr%", '<div class="abstractFr"><a class="abstractFr" href="'.$refs["googletranslate_abstract"].'" rel="noopener" target="_blank">Traduction automatique en Français sur Google Translate</a></div>', $outputString);
233      } else {
234        // TODO: Create a form to send french abstrat to this class
235        // TODO: Allow to store it in a separate file abstractfr_{pmid}.txt
236          $outputString = str_replace("%abstractFr%", '<span class="abstract">'.$refs["abstractFr"].'</span>', $outputString);
237      }
238
239    // Bootstrap listgroup
240    if (strpos($outputString, "%listgroup%") !== false) {
241      if (empty($refs["translated_title"])) {
242      $lg = "<div class='bs-wrap bs-wrap-list-group list-group pubmed'>";
243      $lg .= "<ul class='list-group pubmed'>";
244      $lg .= "<li class='level1 list-group-item list-group-item-warning pubmed'>";
245      $lg .=   "<strong>".$refs["title"]."</strong></li>";
246      } else {
247      $lg = "<div class='bs-wrap bs-wrap-list-group list-group'>";
248      $lg .= "<ul class='list-group'>";
249      $lg .= "<li class='level1 list-group-item list-group-item-warning pubmed'>";
250      $lg .=   "<strong>".$refs["translated_title"]."</strong></li>";
251
252      $lg .= "<li class='level1 list-group-item pubmed'>";
253      $lg .=   " <i class='dw-icons fa fa-file-o fa-fw' style='font-size:16px'></i> ";
254      $lg .=   $refs["title"]."</li>";
255      }
256
257      $lg .= "<li class='level1 list-group-item pubmed'>";
258      $lg .=   " <i class='dw-icons fa fa-users fa-fw' style='font-size:16px'></i>";
259      $lg .=   " <span class='pubmed'><span class='authors'>";
260      $lg .=   implode(', ',$refs["authors"]);
261      $lg .=   "</span></span></li>";
262
263      $lg .= "<li class='level1 list-group-item pubmed'>";
264      $lg .=   " <i class='dw-icons fa fa-newspaper-o fa-fw' style='font-size:16px'></i>";
265      $lg .=   " <span class='pubmed'><span class='journal'><span class='journal_title'>".$refs["journal_title"]."</span></span></span></li>";
266
267      $lg .= "<li class='level1 list-group-item pubmed'>";
268      $lg .=   " <i class='dw-icons fa fa-calendar-check-o fa-fw' style='font-size:16px'></i> ";
269      $lg .=   "<span class='pubmed'><span class='date'>".$refs["year"]." ".$refs["month"]."</span></li>";
270
271      $lg .= "<li class='level1 list-group-item pubmed'>";
272      $lg .=   " <i class='dw-icons fa fa-code fa-fw' style='font-size:16px'></i> ";
273      $lg .=   "<span class='pubmed'><span class='iso'>".$refs["iso"]."</span></li>";
274
275      // Keywords
276      $lg .= "<li class='level1 list-group-item pubmed'>";
277      $lg .=   " <i class='dw-icons fa fa-tags fa-fw' style='font-size:16px'></i> ";
278      if (!empty($refs["mesh"])) {
279        $lg .=   "<span class='mesh'>".implode(', ',$refs["mesh"])."</span> ";
280      } else if (!empty($refs["keywords"])) {
281        $lg .=   "<span class='keywords'>".implode(', ',$refs["keywords"])."</span>";
282      } else {
283        $lg .=   "<span class='keywords'>Aucun mots clés</span>";
284      }
285      $lg .=   "</li>";
286
287      // User added HASHTAGS
288      if (!empty($refs["hashtags"])) {
289      $lg .= "<li class='level1 list-group-item pubmed'>";
290      $lg .=   " <i class='dw-icons fa fa-hashtag fa-fw' style='font-size:16px'></i> ";
291      $lg .=   "<span class='pubmed'><span class='hashtags'>".$refs["hashtags"]."</span></li>";
292      }
293
294      // Links
295      $lg .= "<li class='level1 list-group-item list-group-item-warning pubmed'>";
296      $lg .=   "<strong>Liens</strong></li>";
297
298      $lg .= "<li class='level1 list-group-item pubmed'>";
299      $lg .=  " <i class='dw-icons fa fa-external-link fa-fw' style='font-size:16px'></i>";
300      $lg .=  " <a href='".$refs["googletranslate_abstract"]."' class='list-group-item pubmed' rel='noopener' target='_blank'>Traduction automatique en Français sur Google Translate</a></li>";
301
302      $lg .= "<li class='level1 list-group-item pubmed'>";
303      $lg .=  " <i class='dw-icons fa fa-external-link fa-fw' style='font-size:16px'></i>";
304      $lg .=  " <a href='http://dx.doi.org/".$refs["doi"]."' class='list-group-item pubmed' rel='noopener' target='_blank' title='".$refs["doi"]."'>DOI: ".$refs["doi"]."</a></li>";
305      $lg .= "<li class='level1 list-group-item pubmed'>";
306      $lg .=  " <i class='dw-icons fa fa-external-link fa-fw' style='font-size:16px'></i>";
307      $lg .=  " <a href='".$refs["url"]."' class='list-group-item pubmed' rel='noopener' target='_blank' title='PMID: ".$refs["pmid"]."'>PMID: ".$refs["pmid"]."</a></li>";
308
309      if (!empty($refs["similarurl"])) {
310      $lg .= "<li class='level1 list-group-item pubmed'>";
311      $lg .=  " <i class='dw-icons fa fa-external-link fa-fw' style='font-size:16px'></i>";
312      $lg .=  " <a href='".$refs["similarurl"]."' class='list-group-item pubmed' rel='noopener' target='_blank''>Articles similaires</a></li>";
313      }
314
315      if (!empty($refs["citedbyurl"])) {
316      $lg .= "<li class='level1 list-group-item pubmed'>";
317      $lg .=  " <i class='dw-icons fa fa-external-link fa-fw' style='font-size:16px'></i>";
318      $lg .=  " <a href='".$refs["citedbyurl"]."' class='list-group-item pubmed' rel='noopener' target='_blank''>Cité par</a></li>";
319      }
320
321      if (!empty($refs["referencesurl"])) {
322      $lg .= "<li class='level1 list-group-item pubmed'>";
323      $lg .=  " <i class='dw-icons fa fa-external-link fa-fw' style='font-size:16px'></i>";
324      $lg .=  " <a href='".$refs["referencesurl"]."' class='list-group-item pubmed' rel='noopener' target='_blank''>Références</a></li>";
325      }
326
327      if (!empty($refs["pmcid"])) {
328      $lg .= "<li class='level1 list-group-item pubmed'>";
329      $lg .=  " <i class='dw-icons fa fa-external-link fa-fw' style='font-size:16px'></i>";
330      $lg .=  " <a href='".$refs["pmcurl"]."' class='list-group-item pubmed' rel='noopener' target='_blank''>Texte complet gratuit</a></li>";
331      }
332
333      // Twitter
334      $lg .= "<li class='level1 list-group-item list-group-item-warning pubmed'>";
335      $lg .=   "<strong>Twitter</strong></li>";
336
337      $lg .= "<li class='level1 list-group-item pubmed'>";
338      $lg .=  " <i class='dw-icons fa fa-twitter fa-fw' style='font-size:16px'></i>";
339      $lg .=  " <a href='".$this->_createTwitterUrl($refs)."' class='list-group-item pubmed' rel='noopener' target='_blank''>Twitter cet article (lien vers l'article)</a></li>";
340      $lg .= "<li class='level1 list-group-item pubmed'>";
341      $lg .=  " <i class='dw-icons fa fa-twitter fa-fw' style='font-size:16px'></i>";
342      $lg .=  " <a href='".$this->_createTwitterUrl($refs, true)."' class='list-group-item pubmed' rel='noopener' target='_blank''>Twitter cet article (lien vers cette page)</a></li>";
343
344      $lg .= "</ul>";
345      $lg .= "</div>";
346      $outputString = str_replace("%listgroup%", $lg, hsc($outputString));
347    }
348
349    // Remove double points separated with a span tag
350    $outputString = str_replace(".</span>.",  '.</span>', $outputString);
351
352    return $outputString;
353  }
354
355  /**
356   * Create output
357   * We have different database to extract data
358   * "pmid" = pubmed
359   * "pmcid" = pmc
360   */
361  function render($mode, Doku_Renderer $renderer, $data) {
362    if ($mode != 'xhtml')
363      return false;
364    // Get the command and its arg(s)
365    list($state, $query) = $data;
366    list($base, $req) = $query;
367    list($cmd, $id) = explode(':', $req, 2);
368    $cmd = strtolower($cmd);
369
370    // If command is empty (in this case, command is the numeric pmids)
371    // Catch default command in plugin's preferences
372    $regex = '/^[0-9,]+$/';
373    // if (preg_match($regex, $cmd) === 1) {
374    if (empty($id)) {
375      $id = $cmd;
376      $cmd = $this->documentFormat;
377    }
378
379    // Manage the article reference commands in :
380    //   short, long, long_abstract, vancouver,
381    //   or user
382    $this->outputTpl["user"] = $this->getConf('user_defined_output');
383
384    // Allow user to define a document format
385    if ($cmd === "doc_format") {
386      $this->documentFormat = $id;
387      $this->useDocumentFormat = true;
388      return true;
389    } else if ($this->useDocumentFormat && (!in_array($cmd, $this->commands))) {
390       $cmd = $this->documentFormat;
391    }
392
393    //echo $cmd.PHP_EOL;
394
395    if (array_key_exists($cmd, $this->outputTpl)) {
396      // Check and open multiple PMIDs
397      $multipleIds = strpos($id, ",");
398      if ($multipleIds) {
399        $renderer->doc .= "<ul>";
400      }
401      $id = explode(",", $id);
402
403      // With multiple PMIDs, the first one can be a word
404      if ($id[0] === "sort") {
405        // Remove [0]
406        array_shift($id);
407        // Sort ids
408        sort($id);
409        $id = array_reverse($id);
410      }
411
412      // Remove duplicates
413      $id = array_unique($id, SORT_REGULAR);
414
415      // Add each PMID to the renderer
416      foreach ($id as $curId) {
417        $renderer->doc .= $this->getIdOutput($cmd, $base, $curId, $multipleIds);
418      }
419
420      // Close multiple PMIDs
421      if ($multipleIds) {
422        $renderer->doc .= "</ul>";
423      }
424    } else {
425      // Manage all other commands
426      switch($cmd) {
427        case 'addtt': // Ok PubMed2020
428            // $id = pmid|translatedTitle
429            list($id, $tt) = explode('|', $id, 2);
430            $raw = $this->getMedlineContent($base, $id);
431            if (strpos($raw, "TT  - ") === false) {
432              $raw .= "\nTT  - ".$tt."\n";
433            } else {
434              // Check raw value
435              $pattern = "/TT  - ".$tt."/";
436              if (!preg_match($pattern, $raw)) {
437                $pattern = "/TT  - .*/";
438                $raw = preg_replace($pattern, "\nTT  - ".$tt."\n", $raw);
439              }
440            }
441            $this->pubmedCache->saveRawMedlineContent($base, $raw);
442            return true;
443        case 'addhash_fr': // Ok PubMed2020
444            // $id = pmid|hash1,hash2,hash3
445            list($id, $hash) = explode('|', $id, 2);
446            $raw = $this->getMedlineContent($base, $id);
447            if (strpos($raw, "HASH- ") === false) {
448              $raw .= "\nHASH- ".$hash."\n";
449            } else {
450              // Check raw value
451              $pattern = "/HASH- ".$hash."/";
452              if (!preg_match($pattern, $raw)) {
453                $pattern = "/HASH- .*/";
454                $raw = preg_replace($pattern, "\nHASH- ".$hash."\n", $raw);
455              }
456            }
457            $this->pubmedCache->saveRawMedlineContent($base, $raw);
458            return true;
459        case 'convertid': // Ok PubMed2020
460            $r = $this->pubmed2020->convertId($id);
461            if ($r) {
462              $renderer->doc .= "PMID: ".$r->pmid." ; DOI: ".$r->doi." ; PMC: ".$r->pmcid;
463            } else {
464              $renderer->doc .= "Id not found: ".$id;
465            }
466            return true;
467        case 'test': // Ok PubMed2020
468            $this->runTests();
469            return true;
470        case 'raw_medline': // Ok PubMed2020
471          // Check multiple PMIDs (PMIDs can be passed in a coma separated list)
472          $multipleIds = strpos($id, ",");
473          $id = explode(",", $id);
474          foreach ($id as $curId) {
475            if (!is_numeric($curId)){
476              $renderer->doc .= sprintf($this->getLang('pubmed_wrong_format'));
477              return false;
478            }
479            $raw = $this->getMedlineContent($base, $curId);
480            if (empty($raw)) {
481              $renderer->doc .= sprintf($this->getLang('pubmed_not_found'), $curId);
482              return false;
483            }
484            $renderer->doc .= "<pre>".htmlspecialchars($raw, ENT_QUOTES)."</pre>";
485          }  // Foreach PMIDs
486          return true;
487        case 'clear_raw_medline':
488          $this->pubmedCache->clearCache();
489          $renderer->doc .= 'Cleared.';
490          return true;
491        case 'remove_dir':
492          $this->pubmedCache->removeDir();
493          $renderer->doc .= 'Directory cleared.';
494          return true;
495        case 'search':
496          $link = $this->pubmed2020->getPubmedSearchURL($id);
497          $renderer->doc .='<span class="pubmed">';
498          $renderer->doc .= '<a class="pmid" rel="noopener" target="_blank" href="';
499          $renderer->doc .= $link[1];
500          $renderer->doc .= '">'.$link[0].'</a>';
501          $renderer->doc .='</span>';
502          return true;
503        case 'recreate_cross_refs':
504          $this->pubmedCache->recreateCrossRefFile();
505          return true;
506        case 'full_pdf_list':
507          // Get all PMID from cache
508          $mediaList = array_keys($this->pubmedCache->getAllMediaPaths());
509          // Get all PMID using the local PDF filename
510          $pdfPmids = $this->pubmedCache->GetAllAvailableLocalPdfByPMIDs();
511          // Remove all local PDF PMIDs already in the media list
512          $pdfPmids = array_diff($pdfPmids, $mediaList);
513          // Remove all pdfPmid if present in the mediaList
514          $pdfDois = $this->pubmedCache->GetAllAvailableLocalPdfByDOIs();
515          // Get PMIDs from DOIs
516          $pmids = $this->pubmedCache->PmidFromDoi($pdfDois);
517
518//           $i = 0;
519          foreach($pdfDois as $doi) {
520//             if (++$i == 5)
521//                break;
522            $raw = $this->pubmed2020->getDataFromCtxp($base, "", $doi);
523            if (!empty($raw)) {
524              $this->pubmedCache->saveRawMedlineContent($base, $raw);
525            }
526          }
527
528          // Create a complete list of PMIDs to show
529          //$fullPmids = array_merge($pdfPmids, $pmids, $mediaList);
530          $fullPmids = array_merge($pdfPmids, $pmids);
531          // Check multiple PMIDs (PMIDs can be passed in a coma separated list)
532          $renderer->doc .= "<ul>";
533          foreach($fullPmids as $currentPmid) {
534            $renderer->doc .= $this->getIdOutput("long_abstract", $base, $currentPmid, true);
535          }  // Foreach PMIDs
536          foreach($pdfDois as $doi) {
537            $renderer->doc .=
538                "<a href='".$this->pubmedCache->GetDoiPdfUrl($doi).
539                "' title='".$doi.
540                "'><img src='".$this->pubmedCache->GetDoiPdfThumbnailUrl($doi).
541                "' alt='".$doi.
542                "'/></a>";
543          }  // Foreach PMIDs
544          $renderer->doc .= "</ul>";
545          return true;
546
547        default: // Ok PubMed2020
548          // Command was not found..
549          $renderer->doc .= '<div class="pdb_plugin">';
550          $renderer->doc .= sprintf($this->getLang('plugin_cmd_not_found'),$cmd);
551          $renderer->doc .= '</div>';
552          $renderer->doc .= '<div class="pdb_plugin_text">';
553          $renderer->doc .= $this->getLang('pubmed_available_cmd');
554          $renderer->doc .= '</div>';
555          return true;
556      }
557    }
558  }
559
560
561  /**
562  * Get Medline raw data from cache or get it from NCBI
563  */
564  function getMedlineContent($base, $id) {
565    global $conf;
566    $cached = $this->pubmedCache->getMedlineContent($base, $id);
567    if ($cached !== false) {
568      return $cached;
569    }
570    // Get content from PubMed website
571    $raw = $this->pubmed2020->getDataFromCtxp($base, $id);
572    // Save to cache
573    $this->pubmedCache->saveRawMedlineContent($base, $raw);
574    return $raw;
575  }
576
577  /**
578   * Check PMID format
579   */
580  function checkIdFormat($base, $id) {
581    // Check PMID/PMCID format (numeric, 7 or 8 length)
582    if (!is_numeric($id) || (strlen($id) < 6 || strlen($id) > 8)) {
583      return false;
584    }
585    return true;
586  } // Ok pubmed2020
587
588  /**
589   * Get pubmed string output according to the given unique
590   * ID code passed and the command.
591   * $multipleIds : boolean, use it if the output in inside a multiple ids request
592   */
593  function getIdOutput($cmd, $base, $id, $multipleIds) {
594     if (!$this->checkIdFormat($base, $id)) {
595        return sprintf($this->getLang('pubmed_wrong_format'));
596      }
597
598      // Get article content (from cache or web)
599      $raw = $this->getMedlineContent($base, $id);
600      if (empty($raw)) {
601        return sprintf($this->getLang('pubmed_not_found'), $id);
602        return false;
603      }
604
605      // Get the abstract of the article
606      $refs = $this->pubmed2020->readMedlineContent($raw, $this);
607
608      // Catch updated user output template
609      $outputTpl['user'] = $this->getConf('user_defined_output');
610
611      // Construct reference to article (author.title.rev.year..) according to command
612      $output = "";
613      if ($multipleIds)
614        $output .= "<li>";
615
616      if (empty($this->outputTpl[$cmd]))
617          $cmd = "long_abstract";
618
619      // $cmd contains abstract -> use div instead of span
620      $block = "span";
621      if (strpos($cmd, 'abstract') !== false) {
622        $block = "div";
623      }
624
625      $output .= "<{$block} class=\"pubmed\"><{$block} class=\"{$cmd}\"";
626      if ($multipleIds)
627        $output .= ' style="margin-bottom:1em"';
628      $output .= ">";
629
630      $output .= $this->replaceTokens($this->outputTpl[$cmd], $refs);
631      $output .= "</{$block}></{$block}>";
632      if ($multipleIds)
633        $output .= "</li>";
634
635      return $output;
636  } // Ok pubmed2020
637
638
639  /**
640   * Create a link to Tweet the paper
641   * - $refs is the full paper references (use pubmed2020 class to get it)
642   * - $currentUrl if true tweet with current website URL, if false use the $refs["url"]
643   */
644  function _createTwitterUrl($refs, $currentUrl = false) {
645    // https://developer.twitter.com/en/docs/twitter-for-websites/tweet-button/guides/web-intent
646    // 280 characters when text is combined with any passed hashtags, via, or url parameters.
647
648    // HASHTAGS
649    if (!empty($refs["hashtags"])) {
650      $list = explode(",", $refs["hashtags"]);
651      foreach ($list as &$value) {
652        $value = trim($value);
653        $value = str_replace(" ", "_", $value);
654        $value = str_replace("-", "ー", $value);
655      }
656      $hash = "&hashtags=".implode(",", $list); // Comma separated without #
657    } else {
658      $hash = "";
659    }
660
661    // TEXT
662    if (!empty($refs["translated_title"])) {
663        $txt  = $refs["translated_title"]."\n\n";
664    } else {
665        $txt  = $refs["title"]."\n\n";
666    }
667    $txt .= $refs["journal_iso"]." ".$refs["year"]."\n";
668    $txt  = "&text=".rawurlencode($txt);
669
670    // URL
671    $url = "";
672    // Get current page URL
673    if ($currentUrl) {
674      // Use Twitter URL shorteners
675      // See
676      // $conf['twitter_url_shortener_format_pmid'] = "";
677      // $conf['twitter_url_shortener_format_pmcid'] = "";
678      if (!empty($this->getConf('twitter_url_shortener_format_pmid'))
679          && !empty($refs["pmid"])) {
680        $url = $this->getConf('twitter_url_shortener_format_pmid');
681        $url = str_replace("%PMID%", $refs["pmid"], $url);
682      } else if (!empty($this->getConf('twitter_url_shortener_format_pcmid'))
683                 && !empty($refs["pmid"])) {
684        $url = $this->getConf('twitter_url_shortener_format_pmcid');
685        $url = str_replace("%PMCID%", $refs["pmcid"], $url);
686      } else {
687        global $ID;
688        $url = wl($ID,'',true);
689      }
690    } else {
691      $url = $refs["url"];
692    }
693    $url = "&url=".rawurlencode($url);
694
695    // VIA
696    if (!empty($this->getConf('twitter_via_user_name'))) {
697      $via  = "&via=".$this->getConf('twitter_via_user_name');
698    }
699    //$related = "&related=";
700
701    // Create full link
702    $tweet  = "";
703    $tweet .= str_replace(array("-", "#"), "", $hash);
704    $tweet .= $txt;
705    $tweet .= $url;
706    $tweet .= $via;
707    $tweet  = substr($tweet, 1);
708    $tweet  = sprintf($this->twitterUrl, $tweet);
709
710    return $tweet;
711  }
712
713  /**
714   * Only for dev usage
715   *
716   * Tests: 25617070 for author "de la Cruz M"
717   */
718  function runTests() {
719    echo "Starting PubMed2020 Tests<br>";
720    // Test CTXP URLs
721    $retrieved = $this->pubmed2020->getDataFromCtxp("pmid", "15924077", "doi");
722
723    // Test MedLine Format Reader
724    $myfile = fopen(DOKU_PLUGIN.'pubmed/tests/PM15924077.nbib', "r") or die("Unable to open file!");
725    $s = fread($myfile, filesize(DOKU_PLUGIN.'pubmed/tests/PM15924077.nbib'));
726    fclose($myfile);
727
728    // Check retrieved files
729    if ($retrieved === $s)
730      echo "File Content: Ok".PHP_EOL;
731    else
732      echo "File Content: NOT Ok".PHP_EOL;
733
734    $this->pubmed2020->readMedlineContent($s, "PMID", $this);
735  }
736
737}
738
739?>