xref: /plugin/doi/syntax/isbn.php (revision 19099051d67524067917f46dcae400e7d8a95f79)
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_isbn 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('\[\[isbn>[^\]]+\]\]', $mode, 'plugin_doi_isbn');
33    }
34
35    /** @inheritDoc */
36    public function handle($match, $state, $pos, Doku_Handler $handler)
37    {
38        $isbn = substr($match, 7, -2);
39        $isbn = preg_replace('/[^0-9X]/i', '', $isbn);
40
41        return ['isbn' => $isbn];
42    }
43
44    /** @inheritDoc */
45    public function render($mode, Doku_Renderer $renderer, $data)
46    {
47        $publication = $this->fetchInfo($data['isbn']);
48        $title = $publication['details']['title'] ?? $data['isbn'];
49        $url = $publication['details']['info_url'] ?? 'https://www.google.com/search?q=isbn+' . $data['isbn'];
50
51        if ($mode !== 'xhtml' || !$publication) {
52            $renderer->externallink($url, $title);
53            return true;
54        }
55
56        /** @var Doku_Renderer_xhtml $renderer */
57        $this->formatPub($publication, $renderer);
58
59        return true;
60    }
61
62    /**
63     * Render the given message
64     *
65     * @param array $message
66     * @param Doku_Renderer_xhtml $renderer
67     * @return void
68     */
69    protected function formatPub($message, $renderer)
70    {
71        $url = $message['info_url'];
72        $message = $message['details'];
73
74        $isbn = $message['isbn_13'][0] ?? $message['isbn_10'][0] ?? '';
75        $title = $message['title'] ?? $isbn;
76
77        $class = 'book';
78
79        $authorList = [];
80        foreach ($message['authors'] ?? [] as $author) {
81            $authorList[] = '<strong>' . hsc($author['name']) . '</strong>';
82        }
83
84        $published = $message['publish_date'] ?? '';
85        if (preg_match('/\b(\d{4})\b/', $published, $m)) {
86            $published = ' <span>(' . hsc($m[1]) . ')</span>';
87        } else {
88            $published = '';
89        }
90
91        $publisher = hsc($message['publishers'][0] ?? '');
92
93        //output
94        $renderer->doc .= '<div class="plugin_doi ' . $class . '">';
95        $renderer->externallink($url, $title);
96        $renderer->doc .= $published;
97
98        $renderer->doc .= '<div class="meta">';
99        if ($authorList) {
100            $renderer->doc .= '<span class="authors">' . join(', ', $authorList) . '</span>';
101        }
102        $renderer->doc .= '</div>';
103
104        $renderer->doc .= '<div class="meta">';
105        if ($publisher) {
106            $renderer->doc .= '<span class="publisher">' . $publisher . '</span>';
107        }
108        $renderer->doc .= ' <code class="isbn">ISBN:' . $isbn . '</code>';
109        $renderer->doc .= '</div>';
110
111        $renderer->doc .= '</div>';
112    }
113
114    /**
115     * Fetch the info for the given ISBN
116     *
117     * @param string $isbn
118     * @return false|array
119     */
120    protected function fetchInfo($isbn)
121    {
122        $cache = getCacheName($isbn, '.isbn.json');
123        if (@filemtime($cache) > filemtime(__FILE__)) {
124            $data = json_decode(file_get_contents($cache), true);
125        } else {
126            $http = new \dokuwiki\HTTP\DokuHTTPClient();
127            $json = $http->get('https://openlibrary.org/api/books?jscmd=details&format=json&bibkeys=ISBN:' . $isbn);
128            if (!$json) return false;
129
130            file_put_contents($cache, $json);
131            $data = json_decode($json, true);
132        }
133        return array_shift($data); // first entry
134    }
135}
136
137