Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.
   1  <?php
   2  // This file is part of Moodle - http://moodle.org/
   3  //
   4  // Moodle is free software: you can redistribute it and/or modify
   5  // it under the terms of the GNU General Public License as published by
   6  // the Free Software Foundation, either version 3 of the License, or
   7  // (at your option) any later version.
   8  //
   9  // Moodle is distributed in the hope that it will be useful,
  10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  // GNU General Public License for more details.
  13  //
  14  // You should have received a copy of the GNU General Public License
  15  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  16  
  17  namespace repository_googledocs\local\node;
  18  
  19  /**
  20   * Class used to represent a file node in the googledocs repository.
  21   *
  22   * @package    repository_googledocs
  23   * @copyright  2021 Mihail Geshoski <mihail@moodle.com>
  24   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  25   */
  26  class file_node implements node {
  27  
  28      /** @var string The ID of the file node. */
  29      private $id;
  30  
  31      /** @var string|null The title of the file node. */
  32      private $title;
  33  
  34      /** @var string The name of the file. */
  35      private $name;
  36  
  37      /** @var string|null The file's export format. */
  38      private $exportformat;
  39  
  40      /** @var string The external link to the file. */
  41      private $link;
  42  
  43      /** @var string The timestamp representing the last modified date. */
  44      private $modified;
  45  
  46      /** @var string|null The size of the file. */
  47      private $size;
  48  
  49      /** @var string The thumbnail of the file. */
  50      private $thumbnail;
  51  
  52      /** @var string|null The type of the Google Doc file (document, presentation, etc.), null if it is a regular file. */
  53      private $googledoctype;
  54  
  55      /**
  56       * Constructor.
  57       *
  58       * @param \stdClass $gdfile The Google Drive file object
  59       */
  60      public function __construct(\stdClass $gdfile) {
  61          $this->id = $gdfile->id;
  62          $this->title = $this->generate_file_title($gdfile);
  63          $this->name = $gdfile->name;
  64          $this->exportformat = $this->generate_file_export_format($gdfile);
  65          $this->link = $this->generate_file_link($gdfile);
  66          $this->modified = ($gdfile->modifiedTime) ? strtotime($gdfile->modifiedTime) : '';
  67          $this->size = !empty($gdfile->size) ? $gdfile->size : null;
  68          // Use iconLink as a file thumbnail if set, otherwise use the default icon depending on the file type.
  69          // Note: The Google Drive API can return a link to a preview thumbnail of the file (via thumbnailLink).
  70          // However, in many cases the Google Drive files are not public and an authorized request is required
  71          // to get the thumbnail which we currently do not support. Therefore, to avoid displaying broken
  72          // thumbnail images in the repository, the icon of the Google Drive file is being used as a thumbnail
  73          // instead as it does not require an authorized request.
  74          // Currently, the returned file icon link points to the 16px version of the icon by default which would result
  75          // in displaying 16px file thumbnails in the repository. To avoid this, the link can be slightly modified in
  76          // order to get a larger version of the icon as there isn't an option to request this through the API call.
  77          $this->thumbnail = !empty($gdfile->iconLink) ? str_replace('/16/', '/64/', $gdfile->iconLink) : '';
  78          $this->googledoctype = !isset($gdfile->fileExtension) ?
  79              str_replace('application/vnd.google-apps.', '', $gdfile->mimeType) : null;
  80      }
  81  
  82      /**
  83       * Create a repository file array.
  84       *
  85       * This method returns an array which structure is compatible to represent a file node in the repository.
  86       *
  87       * @return array|null The node array or null if the node could not be created
  88       */
  89      public function create_node_array(): ?array {
  90          // Cannot create the file node if the file title was not generated or the export format.
  91          // This means that the current file type is invalid or unknown.
  92          if (!$this->title || !$this->exportformat) {
  93              return null;
  94          }
  95  
  96          return [
  97              'id' => $this->id,
  98              'title' => $this->title,
  99              'source' => json_encode(
 100                  [
 101                      'id' => $this->id,
 102                      'name' => $this->name,
 103                      'link' => $this->link,
 104                      'exportformat' => $this->exportformat,
 105                      'googledoctype' => $this->googledoctype,
 106                  ]
 107              ),
 108              'date' => $this->modified,
 109              'size' => $this->size,
 110              'thumbnail' => $this->thumbnail,
 111              'thumbnail_height' => 64,
 112              'thumbnail_width' => 64,
 113          ];
 114      }
 115  
 116      /**
 117       * Generates and returns the title for the file node depending on the type of the Google drive file.
 118       *
 119       * @param \stdClass $gdfile The Google Drive file object
 120       * @return string The file title
 121       */
 122      private function generate_file_title(\stdClass $gdfile): ?string {
 123          // Determine the file type through the file extension.
 124          if (isset($gdfile->fileExtension)) { // The file is a regular file.
 125              return $gdfile->name;
 126          } else { // The file is probably a Google Doc file.
 127              // We need to generate the name by appending the proper google doc extension.
 128              $type = str_replace('application/vnd.google-apps.', '', $gdfile->mimeType);
 129  
 130              if ($type === 'document') {
 131                  return "{$gdfile->name}.gdoc";
 132              }
 133              if ($type === 'presentation') {
 134                  return "{$gdfile->name}.gslides";
 135              }
 136              if ($type === 'spreadsheet') {
 137                  return "{$gdfile->name}.gsheet";
 138              }
 139              if ($type === 'drawing') {
 140                  $config = get_config('googledocs');
 141                  $ext = $config->drawingformat;
 142                  return "{$gdfile->name}.{$ext}";
 143              }
 144          }
 145  
 146          return null;
 147      }
 148  
 149      /**
 150       * Generates and returns the file export format depending on the type of the Google drive file.
 151       *
 152       * @param \stdClass $gdfile The Google Drive file object
 153       * @return string The file export format
 154       */
 155      private function generate_file_export_format(\stdClass $gdfile): ?string {
 156          // Determine the file type through the file extension.
 157          if (isset($gdfile->fileExtension)) { // The file is a regular file.
 158              // The file has an extension, therefore we can download it.
 159              return 'download';
 160          } else {
 161              // The file is probably a Google Doc file, we get the corresponding export link.
 162              $type = str_replace('application/vnd.google-apps.', '', $gdfile->mimeType);
 163              $types = get_mimetypes_array();
 164              $config = get_config('googledocs');
 165  
 166              if ($type === 'document' && !empty($config->documentformat)) {
 167                  $ext = $config->documentformat;
 168                  if ($ext === 'rtf') {
 169                      // Moodle user 'text/rtf' as the MIME type for RTF files.
 170                      // Google uses 'application/rtf' for the same type of file.
 171                      // See https://developers.google.com/drive/v3/web/manage-downloads.
 172                      return 'application/rtf';
 173                  } else {
 174                      return $types[$ext]['type'];
 175                  }
 176              }
 177              if ($type === 'presentation' && !empty($config->presentationformat)) {
 178                  $ext = $config->presentationformat;
 179                  return $types[$ext]['type'];
 180              }
 181              if ($type === 'spreadsheet' && !empty($config->spreadsheetformat)) {
 182                  $ext = $config->spreadsheetformat;
 183                  return $types[$ext]['type'];
 184              }
 185              if ($type === 'drawing' && !empty($config->drawingformat)) {
 186                  $ext = $config->drawingformat;
 187                  return $types[$ext]['type'];
 188              }
 189          }
 190  
 191          return null;
 192      }
 193  
 194      /**
 195       * Generates and returns the external link to the file.
 196       *
 197       * @param \stdClass $gdfile The Google Drive file object
 198       * @return string The link to the file
 199       */
 200      private function generate_file_link(\stdClass $gdfile): string {
 201          // If the google drive file has webViewLink set, use it as an external link.
 202          $link = !empty($gdfile->webViewLink) ? $gdfile->webViewLink : '';
 203          // Otherwise, use webContentLink if set or leave the external link empty.
 204          if (empty($link) && !empty($gdfile->webContentLink)) {
 205              $link = $gdfile->webContentLink;
 206          }
 207  
 208          return $link;
 209      }
 210  }