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