1<?php
2/**
3 * DokuWiki Plugin WikipediaSnippet
4 *
5 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
6 * @author  Anika Henke <anika@selfthinker.org>
7 */
8
9if (!defined('DOKU_INC')) die();
10if (!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
11require_once(DOKU_PLUGIN.'syntax.php');
12
13class syntax_plugin_wikipediasnippet extends DokuWiki_Syntax_Plugin {
14
15    function getType() { return 'substition'; }
16    function getPType() { return 'block'; }
17    function getSort() { return 192; }
18
19    function connectTo($mode) {
20        $this->Lexer->addSpecialPattern('{{wp(?:\:[a-z-]+)?>[^}]+}}',$mode,'plugin_wikipediasnippet');
21    }
22
23    function handle($match, $state, $pos, Doku_Handler $handler) {
24        $data = substr($match, 2, -2);
25        list($command, $article) = explode('>', $data);
26
27        // if no specific language was given (e.g. {{wp>Wiki}}), use configured language
28        if (strpos($command, ':') === false) {
29            global $conf;
30            $lang = $conf['lang'];
31
32            // correct some non-standard language codes
33            $langCorrectionsFile = dirname(__FILE__).'/conf/langCorrections.conf';
34            if (@file_exists($langCorrectionsFile)) {
35                $langCorrections = confToHash($langCorrectionsFile);
36                $lang = strtr($lang, $langCorrections);
37            }
38
39        // if different language was given (e.g. {{wp:fr>Wiki}}), use that
40        } else {
41            list($null, $lang) = explode(':', $command);
42        }
43
44        return trim($lang).'::'.trim($article);
45    }
46
47    function render($mode, Doku_Renderer $renderer, $data) {
48        if($mode == 'xhtml') {
49            if ($data) {
50                list($lang, $article) = explode('::', $data);
51                $wpUrl = 'http://'.$lang.'.wikipedia.org/';
52
53                $wpContent = $this->_getWPcontent($article, $lang, $wpUrl);
54                if ($wpContent) {
55                    $renderer->doc .= $wpContent;
56                } else {
57                    // if all fails, build interwiki link
58                    $renderer->doc .= '<a href="'.$wpUrl.'wiki/'.rawurlencode($article).'" class="interwiki iw_wp">'.hsc($article).'</a>';
59                }
60            }
61            // if no parameter was given, just don't display anything
62        }
63    }
64
65    /**
66     * Get the content of the article from Wikipedia, create a useful snippet
67     *   and create its container
68     */
69    function _getWPcontent($article, $articleLang, $wpUrl) {
70        // config options
71        $snippetLength = ($this->getConf('snippetLength')) ? '&exsentences='.$this->getConf('snippetLength') : '&exintro=';
72        $useHtml = ($this->getConf('useHtml')) ? '' : '&explaintext=';
73        $page = '&titles='.rawurlencode($article);
74
75        $url = $wpUrl.'w/api.php?action=query&prop=extracts&redirects=&format=xml'.$snippetLength.$useHtml.$page;
76
77        // fetch article data from Wikipedia
78        $http = new DokuHTTPClient();
79        $http->agent .= ' (DokuWiki WikipediaSnippet Plugin)';
80        $data = $http->get($url);
81        if(!$data) {
82            msg('Error: Fetching the article from Wikipedia failed.', -1);
83            if ($http->error) {
84                msg($http->error, -1);
85            }
86            return false;
87        }
88
89        // parse XML
90        $xml = simplexml_load_string($data, 'SimpleXMLElement');
91        if (!$xml) {
92            msg('Error: Loading the XML failed.', -1);
93            foreach(libxml_get_errors() as $error) {
94                msg($error->message, -1);
95            }
96            libxml_clear_errors();
97            return false;
98        }
99        $title = $xml->query->pages->page['title'];
100        $text = $xml->query->pages->page->extract;
101        if (!$text) {
102            msg('Error: Parsing the XML failed.', -1);
103            $error = $xml->error;
104            if ($error) {
105                msg($error['code'].': '.$error['info'] ,-1);
106            }
107            return false;
108        }
109
110        // @todo: extracts don't seem to have any links or images; when verified, remove:
111        // all relative links should point to wikipedia
112        $text = str_replace('href="/', 'href="'.$wpUrl , $text);
113        // make protocol relative URLs use http
114        $text = str_replace('src="//', 'src="http://' , $text);
115        if (!$this->getConf('useHtml')) {
116            $text = '<p>'.$text.'</p>';
117        }
118
119        $articleLink = $wpUrl.'wiki/'.rawurlencode($article);
120        $langParams = $this->_getLangParams($articleLang);
121
122        // display snippet and container
123        $wpContent  = '<dl class="wpsnip">'.NL;
124        $wpContent .= '  <dt>'.NL;
125        $wpContent .= '    <em>'.sprintf($this->getLang('from'), $wpUrl).'<span>: </span></em>';
126        $wpContent .=      '<cite><strong><a href="'.$articleLink.'" class="interwiki iw_wp">'.$title.'</a></strong></cite> ';
127        $wpContent .= '  </dt>'.NL;
128        $wpContent .= '  <dd><blockquote '.$langParams.'>'.$text.NL.'</blockquote>'.$this->_getWPlicense($wpUrl).'</dd>'.NL;
129        $wpContent .= '</dl>'.NL;
130
131        return $wpContent;
132    }
133
134    /**
135     * Get license under which the content is distributed
136     */
137    function _getWPlicense($wpUrl) {
138        $url = $wpUrl.'w/api.php?action=query&meta=siteinfo&siprop=rightsinfo&format=xml';
139
140        // fetch license data from Wikipedia
141        $http = new DokuHTTPClient();
142        $http->agent .= ' (DokuWiki WikipediaSnippet Plugin)';
143        $data = $http->get($url);
144        if(!$data) return false;
145        $xml = simplexml_load_string($data, 'SimpleXMLElement');
146
147        if (!$xml) return false;
148        $url = $xml->query->rightsinfo['url'];
149        $text = $xml->query->rightsinfo['text'];
150
151        return '<div class="wplicense"><a href="'.$url.'">'.$text.'</a></div>';
152    }
153
154    /**
155     * Get lang and dir parameters to add if different from global lang and dir
156     */
157    function _getLangParams($articleLang) {
158        global $conf;
159        global $lang;
160
161        $diffLang = '';
162        $diffDir  = '';
163
164        if ($conf['lang'] != $articleLang) {
165            $diffLang = 'lang="'.$articleLang.'" xml:lang="'.$articleLang.'"';
166
167            // check lang dir
168            $lang2dirFile = dirname(__FILE__).'/conf/lang2dir.conf';
169            if (@file_exists($lang2dirFile)) {
170                $lang2dir = confToHash($lang2dirFile);
171                $dir = strtr($articleLang, $lang2dir);
172            }
173            // in case lang is not listed
174            if (!isset($dir) || ($dir == $articleLang)) {
175                $dir = $lang['direction'];
176            }
177
178            $diffDir = ($lang['direction'] != $dir) ? 'dir="'.$dir.'"' : '';
179        }
180
181        return $diffLang.' '.$diffDir;
182    }
183
184}//class
185