3 // This file is part of Moodle - http://moodle.org/
5 // Moodle is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
10 // Moodle is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
20 * class for communication with Wikimedia Commons API
22 * @author Dongsheng Cai <dongsheng@moodle.com>, Raul Kern <raunator@gmail.com>
23 * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
26 define('WIKIMEDIA_THUMBS_PER_PAGE', 24);
27 define('WIKIMEDIA_FILE_NS', 6);
28 define('WIKIMEDIA_IMAGE_SIDE_LENGTH', 1024);
29 define('WIKIMEDIA_THUMB_SIZE', 120);
32 private $_conn = null;
33 private $_param = array();
35 public function __construct($url = '') {
37 $this->api
= 'https://commons.wikimedia.org/w/api.php';
41 $this->_param
['format'] = 'php';
42 $this->_param
['redirects'] = true;
43 $this->_conn
= new curl(array('cache'=>true, 'debug'=>false));
45 public function login($user, $pass) {
46 $this->_param
['action'] = 'login';
47 $this->_param
['lgname'] = $user;
48 $this->_param
['lgpassword'] = $pass;
49 $content = $this->_conn
->post($this->api
, $this->_param
);
50 $result = unserialize($content);
51 if (!empty($result['result']['sessionid'])) {
52 $this->userid
= $result['result']['lguserid'];
53 $this->username
= $result['result']['lgusername'];
54 $this->token
= $result['result']['lgtoken'];
60 public function logout() {
61 $this->_param
['action'] = 'logout';
62 $content = $this->_conn
->post($this->api
, $this->_param
);
65 public function get_image_url($titles) {
66 $image_urls = array();
67 $this->_param
['action'] = 'query';
68 if (is_array($titles)) {
69 foreach ($titles as $title) {
70 $this->_param
['titles'] .= ('|'.urldecode($title));
73 $this->_param
['titles'] = urldecode($titles);
75 $this->_param
['prop'] = 'imageinfo';
76 $this->_param
['iiprop'] = 'url';
77 $content = $this->_conn
->post($this->api
, $this->_param
);
78 $result = unserialize($content);
79 foreach ($result['query']['pages'] as $page) {
80 if (!empty($page['imageinfo'][0]['url'])) {
81 $image_urls[] = $page['imageinfo'][0]['url'];
86 public function get_images_by_page($title) {
87 $image_urls = array();
88 $this->_param
['action'] = 'query';
89 $this->_param
['generator'] = 'images';
90 $this->_param
['titles'] = urldecode($title);
91 $this->_param
['prop'] = 'images|info|imageinfo';
92 $this->_param
['iiprop'] = 'url';
93 $content = $this->_conn
->post($this->api
, $this->_param
);
94 $result = unserialize($content);
95 if (!empty($result['query']['pages'])) {
96 foreach ($result['query']['pages'] as $page) {
97 $image_urls[$page['title']] = $page['imageinfo'][0]['url'];
103 * Generate thumbnail URL from image URL.
105 * @param string $image_url
106 * @param int $orig_width
107 * @param int $orig_height
108 * @param int $thumb_width
109 * @param bool $force When true, forces the generation of a thumb URL.
110 * @global object OUTPUT
113 public function get_thumb_url($image_url, $orig_width, $orig_height, $thumb_width = 75, $force = false) {
116 if (!$force && $orig_width <= $thumb_width && $orig_height <= $thumb_width) {
120 $commons_main_dir = 'https://upload.wikimedia.org/wikipedia/commons/';
122 $short_path = str_replace($commons_main_dir, '', $image_url);
123 $extension = strtolower(pathinfo($short_path, PATHINFO_EXTENSION
));
124 if (strcmp($extension, 'gif') == 0) { //no thumb for gifs
125 return $OUTPUT->pix_url(file_extension_icon('.gif', $thumb_width))->out(false);
127 $dir_parts = explode('/', $short_path);
128 $file_name = end($dir_parts);
129 if ($orig_height > $orig_width) {
130 $thumb_width = round($thumb_width * $orig_width/$orig_height);
132 $thumb_url = $commons_main_dir . 'thumb/' . implode('/', $dir_parts) . '/'. $thumb_width .'px-' . $file_name;
133 if (strcmp($extension, 'svg') == 0) { //png thumb for svg-s
134 $thumb_url .= '.png';
142 * Search for images and return photos array.
144 * @param string $keyword
146 * @param array $params additional query params
149 public function search_images($keyword, $page = 0, $params = array()) {
151 $files_array = array();
152 $this->_param
['action'] = 'query';
153 $this->_param
['generator'] = 'search';
154 $this->_param
['gsrsearch'] = $keyword;
155 $this->_param
['gsrnamespace'] = WIKIMEDIA_FILE_NS
;
156 $this->_param
['gsrlimit'] = WIKIMEDIA_THUMBS_PER_PAGE
;
157 $this->_param
['gsroffset'] = $page * WIKIMEDIA_THUMBS_PER_PAGE
;
158 $this->_param
['prop'] = 'imageinfo';
159 $this->_param
['iiprop'] = 'url|dimensions|mime|timestamp|size|user';
160 $this->_param +
= $params;
161 $this->_param +
= array('iiurlwidth' => WIKIMEDIA_IMAGE_SIDE_LENGTH
,
162 'iiurlheight' => WIKIMEDIA_IMAGE_SIDE_LENGTH
);
163 //didn't work with POST
164 $content = $this->_conn
->get($this->api
, $this->_param
);
165 $result = unserialize($content);
166 if (!empty($result['query']['pages'])) {
167 foreach ($result['query']['pages'] as $page) {
168 $title = $page['title'];
169 $file_type = $page['imageinfo'][0]['mime'];
170 $image_types = array('image/jpeg', 'image/png', 'image/gif', 'image/svg+xml');
171 if (in_array($file_type, $image_types)) { //is image
172 $extension = pathinfo($title, PATHINFO_EXTENSION
);
173 $issvg = strcmp($extension, 'svg') == 0;
175 // Get PNG equivalent to SVG files.
180 // The thumbnail (max size requested) is smaller than the original size, we will use the thumbnail.
181 if ($page['imageinfo'][0]['thumbwidth'] < $page['imageinfo'][0]['width']) {
183 //upload scaled down image
184 'source' => $page['imageinfo'][0]['thumburl'],
185 'image_width' => $page['imageinfo'][0]['thumbwidth'],
186 'image_height' => $page['imageinfo'][0]['thumbheight']
188 if ($attrs['image_width'] <= WIKIMEDIA_THUMB_SIZE
&& $attrs['image_height'] <= WIKIMEDIA_THUMB_SIZE
) {
189 $attrs['realthumbnail'] = $attrs['source'];
191 if ($attrs['image_width'] <= 24 && $attrs['image_height'] <= 24) {
192 $attrs['realicon'] = $attrs['source'];
195 // We use the original file.
198 //upload full size image
199 'image_width' => $page['imageinfo'][0]['width'],
200 'image_height' => $page['imageinfo'][0]['height'],
201 'size' => $page['imageinfo'][0]['size']
204 // We cannot use the source when the file is SVG.
206 // So we generate a PNG thumbnail of the file at its original size.
207 $attrs['source'] = $this->get_thumb_url($page['imageinfo'][0]['url'], $page['imageinfo'][0]['width'],
208 $page['imageinfo'][0]['height'], $page['imageinfo'][0]['width'], true);
210 $attrs['source'] = $page['imageinfo'][0]['url'];
214 'realthumbnail' => $this->get_thumb_url($page['imageinfo'][0]['url'], $page['imageinfo'][0]['width'], $page['imageinfo'][0]['height'], WIKIMEDIA_THUMB_SIZE
),
215 'realicon' => $this->get_thumb_url($page['imageinfo'][0]['url'], $page['imageinfo'][0]['width'], $page['imageinfo'][0]['height'], 24),
216 'author' => $page['imageinfo'][0]['user'],
217 'datemodified' => strtotime($page['imageinfo'][0]['timestamp']),
219 } else { // other file types
220 $attrs = array('source' => $page['imageinfo'][0]['url']);
222 $files_array[] = array(
223 'title'=>substr($title, 5), //chop off 'File:'
224 'thumbnail' => $OUTPUT->pix_url(file_extension_icon(substr($title, 5), WIKIMEDIA_THUMB_SIZE
))->out(false),
225 'thumbnail_width' => WIKIMEDIA_THUMB_SIZE
,
226 'thumbnail_height' => WIKIMEDIA_THUMB_SIZE
,
227 'license' => 'cc-sa',
228 // the accessible url of the file
229 'url'=>$page['imageinfo'][0]['descriptionurl']