Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.3.x will end 7 October 2024 (12 months).
  • Bug fixes for security issues in 4.3.x will end 21 April 2025 (18 months).
  • PHP version: minimum PHP 8.0.0 Note: minimum PHP version has increased since Moodle 4.1. PHP 8.2.x is supported too.

Differences Between: [Versions 310 and 403] [Versions 311 and 403] [Versions 39 and 403] [Versions 400 and 403] [Versions 401 and 403] [Versions 402 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      /** @var string API URL. */
  36      protected $api;
  37  
  38      /** @var string user ID. */
  39      protected $userid;
  40  
  41      /** @var string username. */
  42      protected $username;
  43  
  44      /** @var string token key. */
  45      protected $token;
  46  
  47      public function __construct($url = '') {
  48          if (empty($url)) {
  49              $this->api = 'https://commons.wikimedia.org/w/api.php';
  50          } else {
  51              $this->api = $url;
  52          }
  53          $this->_param['format'] = 'php';
  54          $this->_param['redirects'] = true;
  55          $this->_conn = new curl(array('cache'=>true, 'debug'=>false));
  56      }
  57      public function login($user, $pass) {
  58          $this->_param['action']   = 'login';
  59          $this->_param['lgname']   = $user;
  60          $this->_param['lgpassword'] = $pass;
  61          $content = $this->_conn->post($this->api, $this->_param);
  62          $result = unserialize($content);
  63          if (!empty($result['result']['sessionid'])) {
  64              $this->userid = $result['result']['lguserid'];
  65              $this->username = $result['result']['lgusername'];
  66              $this->token = $result['result']['lgtoken'];
  67              return true;
  68          } else {
  69              return false;
  70          }
  71      }
  72      public function logout() {
  73          $this->_param['action']   = 'logout';
  74          $content = $this->_conn->post($this->api, $this->_param);
  75          return;
  76      }
  77      public function get_image_url($titles) {
  78          $image_urls = array();
  79          $this->_param['action'] = 'query';
  80          if (is_array($titles)) {
  81              foreach ($titles as $title) {
  82                  $this->_param['titles'] .= ('|'.urldecode($title));
  83              }
  84          } else {
  85              $this->_param['titles'] = urldecode($titles);
  86          }
  87          $this->_param['prop']   = 'imageinfo';
  88          $this->_param['iiprop'] = 'url';
  89          $content = $this->_conn->post($this->api, $this->_param);
  90          $result = unserialize($content);
  91          foreach ($result['query']['pages'] as $page) {
  92              if (!empty($page['imageinfo'][0]['url'])) {
  93                  $image_urls[] = $page['imageinfo'][0]['url'];
  94              }
  95          }
  96          return $image_urls;
  97      }
  98      public function get_images_by_page($title) {
  99          $image_urls = array();
 100          $this->_param['action'] = 'query';
 101          $this->_param['generator'] = 'images';
 102          $this->_param['titles'] = urldecode($title);
 103          $this->_param['prop']   = 'images|info|imageinfo';
 104          $this->_param['iiprop'] = 'url';
 105          $content = $this->_conn->post($this->api, $this->_param);
 106          $result = unserialize($content);
 107          if (!empty($result['query']['pages'])) {
 108              foreach ($result['query']['pages'] as $page) {
 109                  $image_urls[$page['title']] = $page['imageinfo'][0]['url'];
 110              }
 111          }
 112          return $image_urls;
 113      }
 114      /**
 115       * Generate thumbnail URL from image URL.
 116       *
 117       * @param string $image_url
 118       * @param int $orig_width
 119       * @param int $orig_height
 120       * @param int $thumb_width
 121       * @param bool $force When true, forces the generation of a thumb URL.
 122       * @global object OUTPUT
 123       * @return string
 124       */
 125      public function get_thumb_url($image_url, $orig_width, $orig_height, $thumb_width = 75, $force = false) {
 126          global $OUTPUT;
 127  
 128          if (!$force && $orig_width <= $thumb_width && $orig_height <= $thumb_width) {
 129              return $image_url;
 130          } else {
 131              $thumb_url = '';
 132              $commons_main_dir = 'https://upload.wikimedia.org/wikipedia/commons/';
 133              if ($image_url) {
 134                  $short_path = str_replace($commons_main_dir, '', $image_url);
 135                  $extension = strtolower(pathinfo($short_path, PATHINFO_EXTENSION));
 136                  if (strcmp($extension, 'gif') == 0) {  //no thumb for gifs
 137                      return $OUTPUT->image_url(file_extension_icon('.gif'))->out(false);
 138                  }
 139                  $dir_parts = explode('/', $short_path);
 140                  $file_name = end($dir_parts);
 141                  if ($orig_height > $orig_width) {
 142                      $thumb_width = round($thumb_width * $orig_width/$orig_height);
 143                  }
 144                  $thumb_url = $commons_main_dir . 'thumb/' . implode('/', $dir_parts) . '/'. $thumb_width .'px-' . $file_name;
 145                  if (strcmp($extension, 'svg') == 0) {  //png thumb for svg-s
 146                      $thumb_url .= '.png';
 147                  }
 148              }
 149              return $thumb_url;
 150          }
 151      }
 152  
 153      /**
 154       * Search for images and return photos array.
 155       *
 156       * @param string $keyword
 157       * @param int $page
 158       * @param array $params additional query params
 159       * @return array
 160       */
 161      public function search_images($keyword, $page = 0, $params = array()) {
 162          global $OUTPUT;
 163          $files_array = array();
 164          $this->_param['action'] = 'query';
 165          $this->_param['generator'] = 'search';
 166          $this->_param['gsrsearch'] = $keyword;
 167          $this->_param['gsrnamespace'] = WIKIMEDIA_FILE_NS;
 168          $this->_param['gsrlimit'] = WIKIMEDIA_THUMBS_PER_PAGE;
 169          $this->_param['gsroffset'] = $page * WIKIMEDIA_THUMBS_PER_PAGE;
 170          $this->_param['prop']   = 'imageinfo';
 171          $this->_param['iiprop'] = 'url|dimensions|mime|timestamp|size|user';
 172          $this->_param += $params;
 173          $this->_param += array('iiurlwidth' => WIKIMEDIA_IMAGE_SIDE_LENGTH,
 174              'iiurlheight' => WIKIMEDIA_IMAGE_SIDE_LENGTH);
 175          //didn't work with POST
 176          $content = $this->_conn->get($this->api, $this->_param);
 177          $result = unserialize($content);
 178          if (!empty($result['query']['pages'])) {
 179              foreach ($result['query']['pages'] as $page) {
 180                  $title = $page['title'];
 181                  $file_type = $page['imageinfo'][0]['mime'];
 182                  $image_types = array('image/jpeg', 'image/png', 'image/gif', 'image/svg+xml');
 183                  if (in_array($file_type, $image_types)) {  //is image
 184                      $extension = pathinfo($title, PATHINFO_EXTENSION);
 185                      $issvg = strcmp($extension, 'svg') == 0;
 186  
 187                      // Get PNG equivalent to SVG files.
 188                      if ($issvg) {
 189                          $title .= '.png';
 190                      }
 191  
 192                      // The thumbnail (max size requested) is smaller than the original size, we will use the thumbnail.
 193                      if ($page['imageinfo'][0]['thumbwidth'] < $page['imageinfo'][0]['width']) {
 194                          $attrs = array(
 195                              //upload scaled down image
 196                              'source' => $page['imageinfo'][0]['thumburl'],
 197                              'image_width' => $page['imageinfo'][0]['thumbwidth'],
 198                              'image_height' => $page['imageinfo'][0]['thumbheight']
 199                          );
 200                          if ($attrs['image_width'] <= WIKIMEDIA_THUMB_SIZE && $attrs['image_height'] <= WIKIMEDIA_THUMB_SIZE) {
 201                              $attrs['realthumbnail'] = $attrs['source'];
 202                          }
 203                          if ($attrs['image_width'] <= 24 && $attrs['image_height'] <= 24) {
 204                              $attrs['realicon'] = $attrs['source'];
 205                          }
 206  
 207                      // We use the original file.
 208                      } else {
 209                          $attrs = array(
 210                              //upload full size image
 211                              'image_width' => $page['imageinfo'][0]['width'],
 212                              'image_height' => $page['imageinfo'][0]['height'],
 213                              'size' => $page['imageinfo'][0]['size']
 214                          );
 215  
 216                          // We cannot use the source when the file is SVG.
 217                          if ($issvg) {
 218                              // So we generate a PNG thumbnail of the file at its original size.
 219                              $attrs['source'] = $this->get_thumb_url($page['imageinfo'][0]['url'], $page['imageinfo'][0]['width'],
 220                                  $page['imageinfo'][0]['height'], $page['imageinfo'][0]['width'], true);
 221                          } else {
 222                              $attrs['source'] = $page['imageinfo'][0]['url'];
 223                          }
 224                      }
 225                      $attrs += array(
 226                          'realthumbnail' => $this->get_thumb_url($page['imageinfo'][0]['url'], $page['imageinfo'][0]['width'], $page['imageinfo'][0]['height'], WIKIMEDIA_THUMB_SIZE),
 227                          'realicon' => $this->get_thumb_url($page['imageinfo'][0]['url'], $page['imageinfo'][0]['width'], $page['imageinfo'][0]['height'], 24),
 228                          'author' => $page['imageinfo'][0]['user'],
 229                          'datemodified' => strtotime($page['imageinfo'][0]['timestamp']),
 230                          );
 231                  } else {  // other file types
 232                      $attrs = array('source' => $page['imageinfo'][0]['url']);
 233                  }
 234                  $files_array[] = array(
 235                      'title'=>substr($title, 5),         //chop off 'File:'
 236                      'thumbnail' => $OUTPUT->image_url(file_extension_icon(substr($title, 5)))->out(false),
 237                      'thumbnail_width' => WIKIMEDIA_THUMB_SIZE,
 238                      'thumbnail_height' => WIKIMEDIA_THUMB_SIZE,
 239                      'license' => 'cc-sa',
 240                      // the accessible url of the file
 241                      'url'=>$page['imageinfo'][0]['descriptionurl']
 242                  ) + $attrs;
 243              }
 244          }
 245          return $files_array;
 246      }
 247  
 248  }