xref: /plugin/doi/syntax/doi.php (revision bc72a281ef14844f78565ca3475003d1586a35d0)
1<?php
2
3/**
4 * DokuWiki Plugin doi (Syntax Component)
5 *
6 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
7 * @author  Andreas Gohr <gohr@cosmocode.de>
8 */
9class syntax_plugin_doi_doi extends \dokuwiki\Extension\SyntaxPlugin
10{
11    /** @inheritDoc */
12    public function getType()
13    {
14        return 'substition';
15    }
16
17    /** @inheritDoc */
18    public function getPType()
19    {
20        return 'normal';
21    }
22
23    /** @inheritDoc */
24    public function getSort()
25    {
26        return 155;
27    }
28
29    /** @inheritDoc */
30    public function connectTo($mode)
31    {
32        $this->Lexer->addSpecialPattern('\[\[doi>[^\]]+\]\]', $mode, 'plugin_doi_doi');
33    }
34
35    /** @inheritDoc */
36    public function handle($match, $state, $pos, Doku_Handler $handler)
37    {
38        $doi = substr($match, 6, -2);
39
40        return ['doi' => $doi];
41    }
42
43    /** @inheritDoc */
44    public function render($mode, Doku_Renderer $renderer, $data)
45    {
46        $publication = $this->fetchInfo($data['doi']);
47        $title = $publication['title'][0] ?? $data['doi'];
48        $url = $publication['URL'] ?? 'https://doi.org/' . $data['doi'];
49
50        if ($mode !== 'xhtml' || !$publication) {
51            $renderer->externallink($url, $title);
52            return true;
53        }
54
55        /** @var Doku_Renderer_xhtml $renderer */
56        $this->formatPub($publication, $renderer);
57
58        return true;
59    }
60
61    /**
62     * Render the given message
63     *
64     * @param array $message
65     * @param Doku_Renderer_xhtml $renderer
66     * @return void
67     */
68    protected function formatPub($message, $renderer)
69    {
70        $doi = $message['DOI'];
71        $title = $message['title'] ?? $doi;
72        $url = $message['URL'] ?? 'https://doi.org/' . $doi;
73
74        $class = hsc($message['type']);
75
76        $authorList = [];
77        foreach ($message['author'] ?? $message['editor'] ?? [] as $author) {
78            $authorList[] = '<strong>' . hsc($author['given'].' '.$author['family']) . '</strong>';
79        }
80
81        if (!empty($message['container-title'])) {
82            $journal = $message['container-title'];
83            $journal .= ' ' . join('/', array_filter([$message['volume'] ?? null, $message['issue'] ?? null]));
84            $journal = '<span>' . hsc($journal) . '</span>';
85            if (isset($message['page'])) {
86                $journal .= ' <i>p' . hsc($message['page']) . '</i>';
87            }
88            $journal = ' <span class="journal">' . $journal . '</span>';
89        } else {
90            $journal = '';
91        }
92
93        $published = $message['issued']['date-parts'][0][0] ?? '';
94        if ($published) $published = ' <span>(' . hsc($published) . ')</span>';
95
96        $publisher = hsc($message['publisher'] ?? '');
97
98        //output
99        $renderer->doc .= '<div class="plugin_doi ' . $class . '">';
100        $renderer->externallink($url, $title);
101        $renderer->doc .= $published;
102
103        $renderer->doc .= '<div class="meta">';
104        if ($authorList) {
105            $renderer->doc .= '<span class="authors">' . join(', ', $authorList) . '</span>';
106        }
107        if ($journal) {
108            $renderer->doc .= $journal;
109        }
110        $renderer->doc .= '</div>';
111
112        $renderer->doc .= '<div class="meta">';
113        if ($publisher) {
114            $renderer->doc .= '<span class="publisher">' . $publisher . '</span>';
115        }
116        $renderer->doc .= ' <code class="doi">DOI:' . $doi . '</code>';
117        $renderer->doc .= '</div>';
118
119        $renderer->doc .= '</div>';
120    }
121
122    /**
123     * Fetch the info for the given DOI
124     *
125     * @param string $doi
126     * @return false|array
127     */
128    protected function fetchInfo($doi)
129    {
130        $cache = getCacheName($doi, '.doi.json');
131        if(@filemtime($cache) > filemtime(__FILE__)) {
132            return json_decode(file_get_contents($cache), true);
133        }
134
135        $http = new \dokuwiki\HTTP\DokuHTTPClient();
136        $http->headers['Accept'] = 'application/vnd.citationstyles.csl+json';
137        $json = $http->get('https://doi.org/' . $doi);
138        if (!$json) return false;
139
140        file_put_contents($cache, $json);
141        return json_decode($json, true);
142    }
143}
144
145