xref: /plugin/doi/syntax/doi.php (revision 7195edb0278765975aaf826cd01dd104859d32f0)
1<?php
2
3use dokuwiki\plugin\doi\Resolver\AbstractResolver;
4use \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 */
13class 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        $doi = substr($match, 6, -2);
43
44        return ['id' => $doi];
45    }
46
47    /** @inheritDoc */
48    public function render($mode, Doku_Renderer $renderer, $data)
49    {
50        $resolver = $this->getResolver();
51        $data['id'] = $resolver->cleanID($data['id']);
52
53        try {
54            $publication = $resolver->getData($data['id']);
55        } catch (Exception $e) {
56            msg(hsc($e->getMessage()), -1);
57            $url = $resolver->getFallbackURL($data['id']);
58            $title = $data['id'];
59
60            $renderer->externallink($url, $title);
61            return true;
62        }
63
64        if ($mode === 'xhtml') {
65            /** @var Doku_Renderer_xhtml $renderer */
66            $this->renderXHTML($publication, $renderer);
67        } else {
68            $this->renderAny($publication, $renderer);
69        }
70
71        return true;
72    }
73
74    /**
75     * @return AbstractResolver
76     */
77    protected function getResolver()
78    {
79        return new DoiResolver();
80    }
81
82    /**
83     * Render the given data on the XHTML renderer
84     *
85     * Adds various classes to the output for CSS styling
86     *
87     * @param array $data
88     * @param Doku_Renderer_xhtml $renderer
89     * @return void
90     */
91    protected function renderXHTML($data, $renderer)
92    {
93        $renderer->doc .= '<div class="plugin_doi ' . hsc($data['type']) . '">';
94        $renderer->externallink($data['url'], $data['title']);
95
96        if ($data['published']) {
97            $renderer->doc .= ' <span>(' . hsc($data['published']) . ')</span>';
98        }
99
100        $renderer->doc .= '<div class="meta">';
101        if ($data['authors']) {
102            $authors = array_map(function ($author) {
103                return '<strong>' . hsc($author) . '</strong>';
104            }, $data['authors']);
105            $renderer->doc .= '<span class="authors">' . join(', ', $authors) . '</span>';
106        }
107        if ($data['journal']) {
108            $journal = $data['journal'];
109            $journal .= ' ' . join('/', array_filter([$data['volume'] ?? null, $data['issue'] ?? null]));
110            $journal = '<span>' . hsc($journal) . '</span>';
111            if ($data['page']) {
112                $journal .= ' <i>p' . hsc($data['page']) . '</i>';
113            }
114            $renderer->doc .= ' <span class="journal">' . $journal . '</span>';
115        }
116        $renderer->doc .= '</div>';
117
118        $renderer->doc .= '<div class="meta">';
119        if ($data['publisher']) {
120            $renderer->doc .= '<span class="publisher">' . hsc($data['publisher']) . '</span>';
121        }
122        $renderer->doc .= ' <code class="id">' . $data['idtype'] . ':' . hsc($data['id']) . '</code>';
123        $renderer->doc .= '</div>';
124
125        $renderer->doc .= '</div>';
126    }
127
128    /**
129     * Render the given data on any renderer
130     *
131     * Uses renderer methods only
132     *
133     * @param array $data
134     * @param Doku_Renderer $renderer
135     * @return void
136     */
137    protected function renderAny($data, $renderer)
138    {
139        $renderer->p_open();
140        $renderer->externallink($data['url'], $data['title']);
141
142        if ($data['published']) {
143            $renderer->cdata(' (' . hsc($data['published']) . ')');
144        }
145        $renderer->linebreak();
146
147        if ($data['authors']) {
148            $len = count($data['authors']);
149            for ($i = 0; $i < $len; $i++) {
150                $renderer->strong_open();
151                $renderer->cdata($data['authors'][$i]);
152                $renderer->strong_close();
153                if ($i < $len - 1) {
154                    $renderer->cdata(', ');
155                }
156            }
157
158            if ($data['journal']) {
159                $journal = $data['journal'];
160                $journal .= ' ' . join('/', array_filter([$data['volume'] ?? null, $data['issue'] ?? null]));
161                $renderer->cdata(' ' . $journal);
162            }
163
164            if ($data['page']) {
165                $renderer->cdata(' ');
166                $renderer->emphasis_open();
167                $renderer->cdata('p' . $data['page']);
168                $renderer->emphasis_close();
169            }
170        }
171        $renderer->linebreak();
172
173        if ($data['publisher']) {
174            $renderer->cdata($data['publisher']);
175            $renderer->cdata(' ');
176        }
177        $renderer->monospace_open();
178        $renderer->cdata($data['idtype'] . ':' . hsc($data['id']));
179        $renderer->monospace_close();
180
181        $renderer->p_close();
182    }
183}
184
185