Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.2.x will end 22 April 2024 (12 months).
  • Bug fixes for security issues in 4.2.x will end 7 October 2024 (18 months).
  • PHP version: minimum PHP 8.0.0 Note: minimum PHP version has increased since Moodle 4.1. PHP 8.1.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 core\moodlenet;
  18  
  19  use core\http_client;
  20  use core\oauth2\client;
  21  use stored_file;
  22  use Psr\Http\Message\ResponseInterface;
  23  use Psr\Http\Message\StreamInterface;
  24  
  25  /**
  26   * MoodleNet client which handles direct outbound communication with MoodleNet instances.
  27   *
  28   * @package   core
  29   * @copyright 2023 Michael Hawkins <michaelh@moodle.com>
  30   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  31   */
  32  class moodlenet_client {
  33      /**
  34       * @var string MoodleNet resource creation endpoint URI.
  35       */
  36      protected const API_CREATE_RESOURCE_URI = '/.pkg/@moodlenet/ed-resource/basic/v1/create';
  37  
  38      /**
  39       * @var string MoodleNet scope for creating resources.
  40       */
  41      public const API_SCOPE_CREATE_RESOURCE = '@moodlenet/ed-resource:write.own';
  42  
  43  
  44      /**
  45       * Constructor.
  46       *
  47       * @param http_client $httpclient The httpclient object being used to perform the share.
  48       * @param client $oauthclient The OAuth 2 client for the MoodleNet site being shared to.
  49       */
  50      public function __construct(
  51          protected http_client $httpclient,
  52          protected client $oauthclient,
  53      ) {
  54          // All properties promoted, nothing further required.
  55      }
  56  
  57      /**
  58       * Create a resource on MoodleNet which includes a file.
  59       *
  60       * @param stored_file $file The file data to send to MoodleNet.
  61       * @param string $resourcename The name of the resource being shared.
  62       * @param string $resourcedescription A description of the resource being shared.
  63       * @return \Psr\Http\Message\ResponseInterface The HTTP client response from MoodleNet.
  64       */
  65      public function create_resource_from_stored_file(
  66          stored_file $file,
  67          string $resourcename,
  68          string $resourcedescription,
  69      ): ResponseInterface {
  70          // This may take a long time if a lot of data is being shared.
  71          \core_php_time_limit::raise();
  72  
  73          $moodleneturl = $this->oauthclient->get_issuer()->get('baseurl');
  74          $apiurl = rtrim($moodleneturl, '/') . self::API_CREATE_RESOURCE_URI;
  75          $stream = $file->get_psr_stream();
  76  
  77          $requestdata = $this->prepare_file_share_request_data(
  78              $file->get_filename(),
  79              $file->get_mimetype(),
  80              $stream,
  81              $resourcename,
  82              $resourcedescription,
  83          );
  84  
  85          try {
  86              $response = $this->httpclient->request('POST', $apiurl, $requestdata);
  87          } finally {
  88              $stream->close(); // Always close the request stream ASAP. Or it will remain open till shutdown/destruct.
  89          }
  90  
  91          return $response;
  92      }
  93  
  94      /**
  95       * Prepare the request data required for sharing a file to MoodleNet.
  96       * This creates an array in the format used by \core\httpclient options to send a multipart request.
  97       *
  98       * @param string $filename Name of the file being shared.
  99       * @param string $mimetype Mime type of the file being shared.
 100       * @param StreamInterface $stream Stream of the file being shared.
 101       * @param string $resourcename The name of the resource being shared.
 102       * @param string $resourcedescription A description of the resource being shared.
 103       * @return array Data in the format required to send a file to MoodleNet using \core\httpclient.
 104       */
 105      protected function prepare_file_share_request_data(
 106          string $filename,
 107          string $mimetype,
 108          StreamInterface $stream,
 109          string $resourcename,
 110          string $resourcedescription,
 111      ): array {
 112          return [
 113              'headers' => [
 114                  'Authorization' => 'Bearer ' . $this->oauthclient->get_accesstoken()->token,
 115              ],
 116              'multipart' => [
 117                  [
 118                      'name' => 'metadata',
 119                      'contents' => json_encode([
 120                          'name' => $resourcename,
 121                          'description' => $resourcedescription,
 122                      ]),
 123                      'headers' => [
 124                          'Content-Disposition' => 'form-data; name="."',
 125                      ],
 126                  ],
 127                  [
 128                      'name' => 'filecontents',
 129                      'contents' => $stream,
 130                      'headers' => [
 131                          'Content-Disposition' => 'form-data; name=".resource"; filename="' . $filename . '"',
 132                          'Content-Type' => $mimetype,
 133                          'Content-Transfer-Encoding' => 'binary',
 134                      ],
 135                  ],
 136              ],
 137          ];
 138      }
 139  }