Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.10.x will end 8 November 2021 (12 months).
  • Bug fixes for security issues in 3.10.x will end 9 May 2022 (18 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.

Differences Between: [Versions 310 and 402] [Versions 310 and 403]

   1  <?php
   2  
   3  // This file is part of Moodle - http://moodle.org/
   4  //
   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.
   9  //
  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.
  14  //
  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/>.
  17  
  18  /**
  19   * wikimedia class
  20   * class for communication with Wikimedia Commons API
  21   *
  22   * @author Dongsheng Cai <dongsheng@moodle.com>, Raul Kern <raunator@gmail.com>
  23   * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
  24   */
  25  
  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);
  30  
  31  class wikimedia {
  32      private $_conn  = null;
  33      private $_param = array();
  34  
  35      public function __construct($url = '') {
  36          if (empty($url)) {
  37              $this->api = 'https://commons.wikimedia.org/w/api.php';
  38          } else {
  39              $this->api = $url;
  40          }
  41          $this->_param['format'] = 'php';
  42          $this->_param['redirects'] = true;
  43          $this->_conn = new curl(array('cache'=>true, 'debug'=>false));
  44      }
  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'];
  55              return true;
  56          } else {
  57              return false;
  58          }
  59      }
  60      public function logout() {
  61          $this->_param['action']   = 'logout';
  62          $content = $this->_conn->post($this->api, $this->_param);
  63          return;
  64      }
  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));
  71              }
  72          } else {
  73              $this->_param['titles'] = urldecode($titles);
  74          }
  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'];
  82              }
  83          }
  84          return $image_urls;
  85      }
  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'];
  98              }
  99          }
 100          return $image_urls;
 101      }
 102      /**
 103       * Generate thumbnail URL from image URL.
 104       *
 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
 111       * @return string
 112       */
 113      public function get_thumb_url($image_url, $orig_width, $orig_height, $thumb_width = 75, $force = false) {
 114          global $OUTPUT;
 115  
 116          if (!$force && $orig_width <= $thumb_width && $orig_height <= $thumb_width) {
 117              return $image_url;
 118          } else {
 119              $thumb_url = '';
 120              $commons_main_dir = 'https://upload.wikimedia.org/wikipedia/commons/';
 121              if ($image_url) {
 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->image_url(file_extension_icon('.gif', $thumb_width))->out(false);
 126                  }
 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);
 131                  }
 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';
 135                  }
 136              }
 137              return $thumb_url;
 138          }
 139      }
 140  
 141      /**
 142       * Search for images and return photos array.
 143       *
 144       * @param string $keyword
 145       * @param int $page
 146       * @param array $params additional query params
 147       * @return array
 148       */
 149      public function search_images($keyword, $page = 0, $params = array()) {
 150          global $OUTPUT;
 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;
 174  
 175                      // Get PNG equivalent to SVG files.
 176                      if ($issvg) {
 177                          $title .= '.png';
 178                      }
 179  
 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']) {
 182                          $attrs = array(
 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']
 187                          );
 188                          if ($attrs['image_width'] <= WIKIMEDIA_THUMB_SIZE && $attrs['image_height'] <= WIKIMEDIA_THUMB_SIZE) {
 189                              $attrs['realthumbnail'] = $attrs['source'];
 190                          }
 191                          if ($attrs['image_width'] <= 24 && $attrs['image_height'] <= 24) {
 192                              $attrs['realicon'] = $attrs['source'];
 193                          }
 194  
 195                      // We use the original file.
 196                      } else {
 197                          $attrs = array(
 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']
 202                          );
 203  
 204                          // We cannot use the source when the file is SVG.
 205                          if ($issvg) {
 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);
 209                          } else {
 210                              $attrs['source'] = $page['imageinfo'][0]['url'];
 211                          }
 212                      }
 213                      $attrs += array(
 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']),
 218                          );
 219                  } else {  // other file types
 220                      $attrs = array('source' => $page['imageinfo'][0]['url']);
 221                  }
 222                  $files_array[] = array(
 223                      'title'=>substr($title, 5),         //chop off 'File:'
 224                      'thumbnail' => $OUTPUT->image_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']
 230                  ) + $attrs;
 231              }
 232          }
 233          return $files_array;
 234      }
 235  
 236  }