1 <?php
2 
3 use dokuwiki\plugin\doi\Resolver\AbstractResolver;
4 use \dokuwiki\plugin\doi\Resolver\DoiResolver;
5 
6 
7 /**
8  * DokuWiki Plugin doi (Syntax Component)
9  *
10  * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
11  * @author  Andreas Gohr <gohr@cosmocode.de>
12  */
13 class syntax_plugin_doi_doi extends \dokuwiki\Extension\SyntaxPlugin
14 {
15     /** @inheritDoc */
16     public function getType()
17     {
18         return 'substition';
19     }
20 
21     /** @inheritDoc */
22     public function getPType()
23     {
24         return 'normal';
25     }
26 
27     /** @inheritDoc */
28     public function getSort()
29     {
30         return 155;
31     }
32 
33     /** @inheritDoc */
34     public function connectTo($mode)
35     {
36         $this->Lexer->addSpecialPattern('\[\[doi>[^\]]+\]\]', $mode, 'plugin_doi_doi');
37     }
38 
39     /** @inheritDoc */
40     public function handle($match, $state, $pos, Doku_Handler $handler)
41     {
42         $match = substr($match, 2, -2);
43         list(, $id) = sexplode('>', $match, 2);
44         list($id, $title) = sexplode('|', $id, 2);
45         return ['id' => $id, 'title' => $title];
46     }
47 
48     /** @inheritDoc */
49     public function render($mode, Doku_Renderer $renderer, $data)
50     {
51         $resolver = $this->getResolver();
52         $data['id'] = $resolver->cleanID($data['id']);
53 
54         try {
55             $publication = $resolver->getData($data['id']);
56         } catch (Exception $e) {
57             msg(hsc($e->getMessage()), -1);
58             $url = $resolver->getFallbackURL($data['id']);
59             $title = empty($data['title']) ? $data['id'] : $data['title'];
60 
61             $renderer->externallink($url, $title);
62             return true;
63         }
64 
65         // overwritten title?
66         if (!empty($data['title'])) $publication['title'] = $data['title'];
67 
68         if ($mode === 'xhtml') {
69             /** @var Doku_Renderer_xhtml $renderer */
70             $this->renderXHTML($publication, $renderer);
71         } else {
72             $this->renderAny($publication, $renderer);
73         }
74 
75         return true;
76     }
77 
78     /**
79      * @return AbstractResolver
80      */
81     protected function getResolver()
82     {
83         return new DoiResolver();
84     }
85 
86     /**
87      * Render the given data on the XHTML renderer
88      *
89      * Adds various classes to the output for CSS styling
90      *
91      * @param array $data
92      * @param Doku_Renderer_xhtml $renderer
93      * @return void
94      */
95     protected function renderXHTML($data, $renderer)
96     {
97         $renderer->doc .= '<div class="plugin_doi ' . hsc($data['type']) . '">';
98         $renderer->externallink($data['url'], $data['title']);
99 
100         if ($data['published']) {
101             $renderer->doc .= ' <span>(' . hsc($data['published']) . ')</span>';
102         }
103 
104         $renderer->doc .= '<div class="meta">';
105         if ($data['authors']) {
106             $authors = array_map(function ($author) {
107                 return '<strong>' . hsc($author) . '</strong>';
108             }, $data['authors']);
109             $renderer->doc .= '<span class="authors">' . join(', ', $authors) . '</span>';
110         }
111         if ($data['journal']) {
112             $journal = $data['journal'];
113             $journal .= ' ' . join('/', array_filter([$data['volume'] ?? null, $data['issue'] ?? null]));
114             $journal = '<span>' . hsc($journal) . '</span>';
115             if ($data['page']) {
116                 $journal .= ' <i>p' . hsc($data['page']) . '</i>';
117             }
118             $renderer->doc .= ' <span class="journal">' . $journal . '</span>';
119         }
120         $renderer->doc .= '</div>';
121 
122         $renderer->doc .= '<div class="meta">';
123         if ($data['publisher']) {
124             $renderer->doc .= '<span class="publisher">' . hsc($data['publisher']) . '</span>';
125         }
126         $renderer->doc .= ' <code class="id">' . $data['idtype'] . ':' . hsc($data['id']) . '</code>';
127         $renderer->doc .= '</div>';
128 
129         $renderer->doc .= '</div>';
130     }
131 
132     /**
133      * Render the given data on any renderer
134      *
135      * Uses renderer methods only
136      *
137      * @param array $data
138      * @param Doku_Renderer $renderer
139      * @return void
140      */
141     protected function renderAny($data, $renderer)
142     {
143         $renderer->p_open();
144         $renderer->externallink($data['url'], $data['title']);
145 
146         if ($data['published']) {
147             $renderer->cdata(' (' . hsc($data['published']) . ')');
148         }
149         $renderer->linebreak();
150 
151         if ($data['authors']) {
152             $len = count($data['authors']);
153             for ($i = 0; $i < $len; $i++) {
154                 $renderer->strong_open();
155                 $renderer->cdata($data['authors'][$i]);
156                 $renderer->strong_close();
157                 if ($i < $len - 1) {
158                     $renderer->cdata(', ');
159                 }
160             }
161 
162             if ($data['journal']) {
163                 $journal = $data['journal'];
164                 $journal .= ' ' . join('/', array_filter([$data['volume'] ?? null, $data['issue'] ?? null]));
165                 $renderer->cdata(' ' . $journal);
166             }
167 
168             if ($data['page']) {
169                 $renderer->cdata(' ');
170                 $renderer->emphasis_open();
171                 $renderer->cdata('p' . $data['page']);
172                 $renderer->emphasis_close();
173             }
174         }
175         $renderer->linebreak();
176 
177         if ($data['publisher']) {
178             $renderer->cdata($data['publisher']);
179             $renderer->cdata(' ');
180         }
181         $renderer->monospace_open();
182         $renderer->cdata($data['idtype'] . ':' . hsc($data['id']));
183         $renderer->monospace_close();
184 
185         $renderer->p_close();
186     }
187 }
188 
189