Differences Between: [Versions 402 and 403]
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 cm_info; 20 use core\event\moodlenet_resource_exported; 21 use core\oauth2\client; 22 use moodle_exception; 23 use stored_file; 24 25 /** 26 * API for sharing Moodle LMS activities to 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 activity_sender extends resource_sender { 33 34 /** 35 * @var cm_info The context module info object for the activity being shared. 36 */ 37 protected cm_info $cminfo; 38 39 /** 40 * Class constructor. 41 * 42 * @param int $cmid The course module ID of the activity being shared 43 * @param int $userid The user ID who is sharing the activity 44 * @param moodlenet_client $moodlenetclient The moodlenet_client object used to perform the share 45 * @param client $oauthclient The OAuth 2 client for the MoodleNet instance 46 * @param int $shareformat The data format to share in. Defaults to a Moodle backup (SHARE_FORMAT_BACKUP) 47 */ 48 public function __construct( 49 int $cmid, 50 protected int $userid, 51 protected moodlenet_client $moodlenetclient, 52 protected client $oauthclient, 53 protected int $shareformat = self::SHARE_FORMAT_BACKUP, 54 ) { 55 parent::__construct($cmid, $userid, $moodlenetclient, $oauthclient, $shareformat); 56 [$this->course, $this->cminfo] = get_course_and_cm_from_cmid($cmid); 57 $this->packager = new activity_packager($this->cminfo, $this->userid); 58 } 59 60 /** 61 * Share an activity/resource to MoodleNet. 62 * 63 * @return array The HTTP response code from MoodleNet and the MoodleNet draft resource URL (URL empty string on fail). 64 * Format: ['responsecode' => 201, 'drafturl' => 'https://draft.mnurl/here'] 65 * @deprecated since Moodle 4.3 66 * @todo Final deprecation MDL-79086 67 */ 68 public function share_activity(): array { 69 debugging('Method share_activity is deprecated, use share_resource instead.', DEBUG_DEVELOPER); 70 return $this->share_resource(); 71 } 72 73 /** 74 * Share an activity/resource to MoodleNet. 75 * 76 * @return array The HTTP response code from MoodleNet and the MoodleNet draft resource URL (URL empty string on fail). 77 * Format: ['responsecode' => 201, 'drafturl' => 'https://draft.mnurl/here'] 78 */ 79 public function share_resource(): array { 80 $accesstoken = ''; 81 $resourceurl = ''; 82 $issuer = $this->oauthclient->get_issuer(); 83 84 // Check user can share to the requested MoodleNet instance. 85 $coursecontext = \core\context\course::instance($this->course->id); 86 $usercanshare = utilities::can_user_share($coursecontext, $this->userid); 87 88 if ($usercanshare && utilities::is_valid_instance($issuer) && $this->oauthclient->is_logged_in()) { 89 $accesstoken = $this->oauthclient->get_accesstoken()->token; 90 } 91 92 // Throw an exception if the user is not currently set up to be able to share to MoodleNet. 93 if (!$accesstoken) { 94 throw new moodle_exception('moodlenet:usernotconfigured'); 95 } 96 97 // Attempt to prepare and send the resource if validation has passed and we have an OAuth 2 token. 98 99 // Prepare file in requested format. 100 $filedata = $this->prepare_share_contents(); 101 102 // If we have successfully prepared a file to share of permitted size, share it to MoodleNet. 103 if (!empty($filedata)) { 104 // Avoid sending a file larger than the defined limit. 105 $filesize = $filedata->get_filesize(); 106 if ($filesize > self::MAX_FILESIZE) { 107 $filedata->delete(); 108 throw new moodle_exception('moodlenet:sharefilesizelimitexceeded', 'core', '', [ 109 'filesize' => $filesize, 110 'filesizelimit' => self::MAX_FILESIZE, 111 ]); 112 } 113 114 // MoodleNet only accept plaintext descriptions. 115 $resourcedescription = $this->get_resource_description($coursecontext); 116 117 $response = $this->moodlenetclient->create_resource_from_stored_file( 118 $filedata, 119 $this->cminfo->name, 120 $resourcedescription, 121 ); 122 $responsecode = $response->getStatusCode(); 123 124 $responsebody = json_decode($response->getBody()); 125 $resourceurl = $responsebody->homepage ?? ''; 126 127 // Delete the generated file now it is no longer required. 128 // (It has either been sent, or failed - retries not currently supported). 129 $filedata->delete(); 130 } 131 132 // Log every attempt to share (and whether or not it was successful). 133 $this->log_event($coursecontext, $this->cminfo->id, $resourceurl, $responsecode); 134 135 return [ 136 'responsecode' => $responsecode, 137 'drafturl' => $resourceurl, 138 ]; 139 } 140 141 /** 142 * Log an event to the admin logs for an outbound share attempt. 143 * 144 * @param \context $coursecontext The course context being shared from. 145 * @param int $cmid The CMID of the activity being shared. 146 * @param string $resourceurl The URL of the draft resource if it was created. 147 * @param int $responsecode The HTTP response code describing the outcome of the attempt. 148 * @return void 149 */ 150 protected function log_event( 151 \core\context $coursecontext, 152 int $cmid, 153 string $resourceurl, 154 int $responsecode, 155 ): void { 156 $event = moodlenet_resource_exported::create([ 157 'context' => $coursecontext, 158 'other' => [ 159 'cmids' => [$cmid], 160 'resourceurl' => $resourceurl, 161 'success' => ($responsecode == 201), 162 ], 163 ]); 164 $event->trigger(); 165 } 166 167 /** 168 * Fetch the description for the resource being created, in a supported text format. 169 * 170 * @param \context $coursecontext The course context being shared from. 171 * @return string Converted activity description. 172 */ 173 protected function get_resource_description( 174 \context $coursecontext, 175 ): string { 176 global $PAGE, $DB; 177 // We need to set the page context here because content_to_text and format_text will need the page context to work. 178 $PAGE->set_context($coursecontext); 179 180 $intro = $DB->get_record($this->cminfo->modname, ['id' => $this->cminfo->instance], 'intro, introformat', MUST_EXIST); 181 $processeddescription = strip_tags($intro->intro); 182 $processeddescription = content_to_text(format_text( 183 $processeddescription, 184 $intro->introformat, 185 ), $intro->introformat); 186 187 return $processeddescription; 188 } 189 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body