From f9979de2a9f291b9c8db7d540f43aa469949865e Mon Sep 17 00:00:00 2001 From: Muhammad Arnaldo Date: Mon, 2 Feb 2026 21:44:04 +0700 Subject: [PATCH] MDL-87708 core: Remove MoodleNet outbound sharing Part of MDL-87350 --- .upgradenotes/MDL-87350-2026020304090981.yml | 10 + public/lang/en/admin.php | 2 - public/lang/en/cache.php | 1 - public/lang/en/error.php | 4 - public/lang/en/moodle.php | 40 --- public/lang/en/role.php | 2 - public/lib/apis.json | 5 - .../event/moodlenet_resource_exported.php | 78 ------ .../classes/external/moodlenet_auth_check.php | 148 ---------- .../moodlenet_get_share_info_activity.php | 152 ----------- .../moodlenet_get_shared_course_info.php | 143 ---------- .../external/moodlenet_send_activity.php | 185 ------------- .../external/moodlenet_send_course.php | 244 ----------------- .../classes/moodlenet/activity_packager.php | 69 ----- .../lib/classes/moodlenet/activity_sender.php | 176 ------------ .../lib/classes/moodlenet/course_packager.php | 64 ----- .../moodlenet/course_partial_packager.php | 99 ------- .../moodlenet/course_partial_sender.php | 100 ------- .../lib/classes/moodlenet/course_sender.php | 180 ------------- .../classes/moodlenet/moodlenet_client.php | 139 ---------- .../classes/moodlenet/resource_packager.php | 191 ------------- .../lib/classes/moodlenet/resource_sender.php | 103 ------- .../moodlenet/share_progress_table.php | 252 ------------------ .../lib/classes/moodlenet/share_recorder.php | 132 --------- public/lib/classes/moodlenet/utilities.php | 123 --------- public/lib/classes/privacy/provider.php | 59 +--- public/lib/db/access.php | 20 -- public/lib/db/caches.php | 13 - public/lib/db/install.xml | 15 -- public/lib/db/services.php | 30 --- public/lib/db/upgrade.php | 34 ++- .../send_activity_modal_base.mustache | 60 ----- .../send_activity_modal_done.mustache | 57 ---- .../send_activity_modal_footer_share.mustache | 28 -- .../send_activity_modal_footer_view.mustache | 26 -- .../send_activity_modal_packaging.mustache | 28 -- public/moodlenet/shareprogress.php | 56 ---- public/version.php | 2 +- 38 files changed, 47 insertions(+), 3023 deletions(-) create mode 100644 .upgradenotes/MDL-87350-2026020304090981.yml delete mode 100644 public/lib/classes/event/moodlenet_resource_exported.php delete mode 100644 public/lib/classes/external/moodlenet_auth_check.php delete mode 100644 public/lib/classes/external/moodlenet_get_share_info_activity.php delete mode 100644 public/lib/classes/external/moodlenet_get_shared_course_info.php delete mode 100644 public/lib/classes/external/moodlenet_send_activity.php delete mode 100644 public/lib/classes/external/moodlenet_send_course.php delete mode 100644 public/lib/classes/moodlenet/activity_packager.php delete mode 100644 public/lib/classes/moodlenet/activity_sender.php delete mode 100644 public/lib/classes/moodlenet/course_packager.php delete mode 100644 public/lib/classes/moodlenet/course_partial_packager.php delete mode 100644 public/lib/classes/moodlenet/course_partial_sender.php delete mode 100644 public/lib/classes/moodlenet/course_sender.php delete mode 100644 public/lib/classes/moodlenet/moodlenet_client.php delete mode 100644 public/lib/classes/moodlenet/resource_packager.php delete mode 100644 public/lib/classes/moodlenet/resource_sender.php delete mode 100644 public/lib/classes/moodlenet/share_progress_table.php delete mode 100644 public/lib/classes/moodlenet/share_recorder.php delete mode 100644 public/lib/classes/moodlenet/utilities.php delete mode 100644 public/lib/templates/moodlenet/send_activity_modal_base.mustache delete mode 100644 public/lib/templates/moodlenet/send_activity_modal_done.mustache delete mode 100644 public/lib/templates/moodlenet/send_activity_modal_footer_share.mustache delete mode 100644 public/lib/templates/moodlenet/send_activity_modal_footer_view.mustache delete mode 100644 public/lib/templates/moodlenet/send_activity_modal_packaging.mustache delete mode 100644 public/moodlenet/shareprogress.php diff --git a/.upgradenotes/MDL-87350-2026020304090981.yml b/.upgradenotes/MDL-87350-2026020304090981.yml new file mode 100644 index 00000000000..442f64de040 --- /dev/null +++ b/.upgradenotes/MDL-87350-2026020304090981.yml @@ -0,0 +1,10 @@ +issueNumber: MDL-87350 +notes: + core: + - message: >- + MoodleNet outbound sharing functionality has been removed. All classes, + functions, web services, and entry files related to outbound sharing + have been removed. The OAuth2 service type 'moodlenet' has also been + removed. There is no replacement for this functionality as MoodleNet + outbound sharing was an experimental feature that is being discontinued. + type: removed diff --git a/public/lang/en/admin.php b/public/lang/en/admin.php index 2d9f4591e5a..f9cb546d084 100644 --- a/public/lang/en/admin.php +++ b/public/lang/en/admin.php @@ -622,8 +622,6 @@ $string['enableplugin'] = 'Enable {$a}'; $string['enablerecordcache'] = 'Enable record cache'; $string['enablerssfeeds'] = 'Enable RSS feeds'; $string['enablesearchareas'] = 'Enable search areas'; -$string['enablesharingtomoodlenet'] = 'Enable sharing to MoodleNet (outbound)'; -$string['enablesharingtomoodlenet_desc'] = 'Enable users to share course content to a configured MoodleNet instance if they have the relevant capability.'; $string['enablestats'] = 'Enable statistics'; $string['enabletrusttext'] = 'Enable trusted content'; $string['enableuserfeedback'] = 'Enable feedback about this software'; diff --git a/public/lang/en/cache.php b/public/lang/en/cache.php index aa2561887e5..be7fa187c97 100644 --- a/public/lang/en/cache.php +++ b/public/lang/en/cache.php @@ -76,7 +76,6 @@ $string['cachedef_langmenu'] = 'List of available languages'; $string['cachedef_license'] = 'List of licences'; $string['cachedef_message_time_last_message_between_users'] = 'Time created for most recent message in a conversation'; $string['cachedef_modelfirstanalyses'] = 'First analysis by model and analysable'; -$string['cachedef_moodlenet_usercanshare'] = 'Users can share resources to MoodleNet'; $string['cachedef_locking'] = 'Locking'; $string['cachedef_message_processors_enabled'] = "Message processors enabled status"; $string['cachedef_contextwithinsights'] = 'Context with insights'; diff --git a/public/lang/en/error.php b/public/lang/en/error.php index 61887881ded..db7f0f840ab 100644 --- a/public/lang/en/error.php +++ b/public/lang/en/error.php @@ -427,10 +427,6 @@ $string['moduledisable'] = 'This module ({$a}) has been disabled for this partic $string['moduledoesnotexist'] = 'This module does not exist'; $string['moduleinstancedoesnotexist'] = 'The instance of this module does not exist'; $string['modulemissingcode'] = 'Module {$a} is missing the code needed to perform this function'; -$string['moodlenet:invalidshareformat'] = 'Incorrect MoodleNet share format'; -$string['moodlenet:invalidsharestatus'] = 'Incorrect MoodleNet share status'; -$string['moodlenet:invalidsharetype'] = 'Invalid MoodleNet share type'; -$string['moodlenet:usernotconfigured'] = 'You do not have permission to share content to MoodleNet, or your account is incorrectly configured.'; $string['movecatcontentstoroot'] = 'Moving the category content to root is not allowed. You must move the contents to an existing category!'; $string['movecatcontentstoselected'] = 'Some category content cannot be moved into the selected category.'; $string['movecategorynotpossible'] = 'You cannot move category \'{$a}\' into the selected category.'; diff --git a/public/lang/en/moodle.php b/public/lang/en/moodle.php index e0b4312af01..0a1e027ebc4 100644 --- a/public/lang/en/moodle.php +++ b/public/lang/en/moodle.php @@ -1388,38 +1388,6 @@ $string['moodledocslink'] = 'Documentation for this page'; $string['moodleversion'] = 'Moodle version'; $string['moodlerelease'] = 'Moodle release'; $string['moodleservicesandsupport'] = 'Services and support'; -$string['moodlenet:cannotconnecttoserver'] = 'Cannot connect to MoodleNet server'; -$string['moodlenet:columnname'] = 'Name'; -$string['moodlenet:columnsenddate'] = 'Send date'; -$string['moodlenet:columnsendstatus'] = 'Send status'; -$string['moodlenet:columntype'] = 'Type'; -$string['moodlenet:configoauthservice'] = 'Select a MoodleNet OAuth 2 service to enable sharing to that MoodleNet site. If the service doesn\'t exist yet, you will need to create it.'; -$string['moodlenet:deletedactivity'] = 'Deleted activity'; -$string['moodlenet:deletedcourse'] = 'Deleted course'; -$string['moodlenet:eventresourceexported'] = 'Resource exported'; -$string['moodlenet:gotomoodlenet'] = 'Go to MoodleNet drafts'; -$string['moodlenet:issuerisnotauthorized'] = 'MoodleNet issuer is not authorised'; -$string['moodlenet:issuerisnotenabled'] = 'MoodleNet issuer is not enabled'; -$string['moodlenet:issuerisnotset'] = 'MoodleNet issuer is not set at site administration'; -$string['moodlenet:nosharedresources'] = 'There are no shared resources to display at this time.'; -$string['moodlenet:outboundsettings'] = 'MoodleNet outbound settings'; -$string['moodlenet:sharenoticeactivity'] = 'This activity is being shared with MoodleNet as a resource.'; -$string['moodlenet:sharenoticecourse'] = 'This course is being shared with MoodleNet as a resource.'; -$string['moodlenet:sharenoticepartial'] = 'The selected activities are being shared with MoodleNet as a resource.'; -$string['moodlenet:sharenoticepartialactivitynumber'] = '{$a} activities will be included in the course.'; -$string['moodlenet:sharefailtitle'] = 'Something went wrong'; -$string['moodlenet:sharefailtext'] = 'There was an error sharing your content to MoodleNet.
Please try again later.'; -$string['moodlenet:sharefailtextwithsitesupport'] = 'There was an error sharing your content to MoodleNet.
Please try again later or contact site support.'; -$string['moodlenet:sharefilesizelimitexceeded'] = 'The size of the resource being shared ({$a->filesize} bytes) exceeds the limit of {$a->filesizelimit} bytes.'; -$string['moodlenet:shareprogress'] = 'MoodleNet share progress'; -$string['moodlenet:shareprogressinfo'] = 'The list shows courses and activities you have shared to MoodleNet.
Click the resource name to view in MoodleNet.'; -$string['moodlenet:sharesuccesstitle'] = 'Saved to MoodleNet drafts'; -$string['moodlenet:sharesuccesstext'] = "Almost done! Visit your drafts in MoodleNet to finish sharing your content."; -$string['moodlenet:sharetomoodlenet'] = 'Share to MoodleNet'; -$string['moodlenet:sharingstatus'] = 'Sharing to MoodleNet'; -$string['moodlenet:sharinglargefile'] = "Large files can take some time."; -$string['moodlenet:sharingto'] = 'Sharing to: '; -$string['moodlenet:packagingandsending'] = 'Packaging your file and sending to MoodleNet...'; $string['more'] = 'more'; $string['morehelp'] = 'More help'; $string['morehelpaboutmodule'] = 'More help about the {$a} activity'; @@ -1741,14 +1709,6 @@ $string['privacy:metadata:log:module'] = 'module'; $string['privacy:metadata:log:time'] = 'The time when the action took place'; $string['privacy:metadata:log:url'] = 'The URL related to the event'; $string['privacy:metadata:log:userid'] = 'The ID of the user who performed the action'; -$string['privacy:metadata:moodlenet_share_progress'] = 'MoodleNet share progress details'; -$string['privacy:metadata:moodlenet_share_progress:type'] = 'The type of share that was performed'; -$string['privacy:metadata:moodlenet_share_progress:courseid'] = 'The associated course ID'; -$string['privacy:metadata:moodlenet_share_progress:cmid'] = 'The associated course module ID'; -$string['privacy:metadata:moodlenet_share_progress:userid'] = 'The user that performed the share'; -$string['privacy:metadata:moodlenet_share_progress:timecreated'] = 'The time the share was performed'; -$string['privacy:metadata:moodlenet_share_progress:resourceurl'] = 'The returned URL from MoodleNet after a successful share'; -$string['privacy:metadata:moodlenet_share_progress:status'] = 'The resulting status of the share'; $string['privacy:metadata:oauth2_refresh_token'] = 'Refresh token used in OAuth 2.0 communication'; $string['privacy:metadata:oauth2_refresh_token:issuerid'] = 'The ID of the issuer to which the token corresponds'; $string['privacy:metadata:oauth2_refresh_token:scopehash'] = 'The ID of the user to whom the token corresponds'; diff --git a/public/lang/en/role.php b/public/lang/en/role.php index 2107d3c77cf..31e71086db0 100644 --- a/public/lang/en/role.php +++ b/public/lang/en/role.php @@ -324,8 +324,6 @@ $string['manager'] = 'Manager'; $string['managerdescription'] = 'Managers can access courses and modify them, but usually do not participate in them.'; $string['manageroles'] = 'Manage roles'; $string['maybeassignedin'] = 'Context types where this role may be assigned'; -$string['moodlenet:shareactivity'] = 'Share activities to MoodleNet'; -$string['moodlenet:sharecourse'] = 'Share course to MoodleNet'; $string['morethan'] = 'More than {$a}'; $string['multipleroles'] = 'Multiple roles'; $string['my:manageblocks'] = 'Manage Dashboard page blocks'; diff --git a/public/lib/apis.json b/public/lib/apis.json index a765940c784..6821d49698f 100644 --- a/public/lib/apis.json +++ b/public/lib/apis.json @@ -184,11 +184,6 @@ "allowedlevel2": true, "allowedspread": true }, - "moodlenet": { - "component": "core", - "allowedlevel2": false, - "allowedspread": false - }, "navigation": { "component": "core", "allowedlevel2": true, diff --git a/public/lib/classes/event/moodlenet_resource_exported.php b/public/lib/classes/event/moodlenet_resource_exported.php deleted file mode 100644 index 967dd27d08e..00000000000 --- a/public/lib/classes/event/moodlenet_resource_exported.php +++ /dev/null @@ -1,78 +0,0 @@ -. - -namespace core\event; - -/** - * MoodleNet send attempt event. - * - * @package core - * @copyright 2023 Michael Hawkins - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class moodlenet_resource_exported extends \core\event\base { - - /** - * Set basic properties for the event. - * - * @return void - */ - protected function init(): void { - $this->data['crud'] = 'c'; - - // Used by teachers, but not for direct educational value to their students. - $this->data['edulevel'] = self::LEVEL_OTHER; - } - - /** - * Fetch the localised general event name. - * - * @return string - */ - public static function get_name(): string { - return get_string('moodlenet:eventresourceexported'); - } - - /** - * Fetch the non-localised event description. - * This description format is designed to work for both single activity and course sharing. - * - * @return string - */ - public function get_description() { - $outcome = $this->other['success'] ? 'successfully shared' : 'failed to share'; - - if (!empty($this->other['cmids'])) { - $cmids = implode("', '", $this->other['cmids']); - $description = "The user with id '{$this->userid}' {$outcome} activities to MoodleNet with the " . - "following course module ids, from context with id '{$this->data['contextid']}': '{$cmids}'."; - } else if (!empty($this->other['courseid'])) { - $courseid = implode("', '", $this->other['courseid']); - $description = "The user with id '{$this->userid}' {$outcome} course to MoodleNet with the " . - "following course id, from context with id '{$this->data['contextid']}': '{$courseid}'."; - } - - return rtrim($description, ", '"); - } - - /** - * Returns relevant URL. - * @return \moodle_url - */ - public function get_url() { - return new \moodle_url($this->other['resourceurl']); - } -} diff --git a/public/lib/classes/external/moodlenet_auth_check.php b/public/lib/classes/external/moodlenet_auth_check.php deleted file mode 100644 index 79553c68b6d..00000000000 --- a/public/lib/classes/external/moodlenet_auth_check.php +++ /dev/null @@ -1,148 +0,0 @@ -. - -namespace core\external; - -use context_course; -use core\moodlenet\moodlenet_client; -use core\moodlenet\utilities; -use core\oauth2\api; -use core_external\external_api; -use core_external\external_function_parameters; -use core_external\external_single_structure; -use core_external\external_value; -use core_external\external_warnings; -use moodle_url; - -/** - * The external API to check whether a user has authorized for a given MoodleNet OAuth 2 issuer. - * - * @package core - * @copyright 2023 Huong Nguyen - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class moodlenet_auth_check extends external_api { - - /** - * Returns description of parameters. - * - * @return external_function_parameters - * @since Moodle 4.2 - */ - public static function execute_parameters(): external_function_parameters { - return new external_function_parameters([ - 'issuerid' => new external_value(PARAM_INT, 'OAuth 2 issuer ID', VALUE_REQUIRED), - 'courseid' => new external_value(PARAM_INT, 'Course ID', VALUE_REQUIRED), - ]); - } - - /** - * External function to check if the user is already authorized with MoodleNet. - * - * @param int $issuerid Issuer Id. - * @param int $courseid The course ID that contains the activity which being shared - * @return array - * @since Moodle 4.2 - */ - public static function execute(int $issuerid, int $courseid): array { - global $USER; - [ - 'issuerid' => $issuerid, - 'courseid' => $courseid, - ] = self::validate_parameters(self::execute_parameters(), [ - 'issuerid' => $issuerid, - 'courseid' => $courseid, - ]); - - // Check capability. - $coursecontext = context_course::instance($courseid); - $usercanshareactivity = utilities::can_user_share($coursecontext, $USER->id, 'activity'); - $usercansharecourse = utilities::can_user_share($coursecontext, $USER->id, 'course'); - if (!$usercanshareactivity && !$usercansharecourse) { - return self::return_errors($courseid, 'errorpermission', - get_string('nopermissions', 'error', get_string('moodlenet:sharetomoodlenet', 'moodle'))); - } - - // Get the issuer. - $issuer = api::get_issuer($issuerid); - // Validate the issuer and check if it is enabled or not. - if (!utilities::is_valid_instance($issuer)) { - return self::return_errors($issuerid, 'errorissuernotenabled', get_string('invalidparameter', 'debug')); - } - - $returnurl = new moodle_url('/admin/moodlenet_oauth2_callback.php'); - $returnurl->param('issuerid', $issuerid); - $returnurl->param('callback', 'yes'); - $returnurl->param('sesskey', sesskey()); - - // Get the OAuth Client. - if (!$oauthclient = api::get_user_oauth_client($issuer, $returnurl, moodlenet_client::API_SCOPE_CREATE_RESOURCE, true)) { - return self::return_errors($issuerid, 'erroroauthclient', get_string('invalidparameter', 'debug')); - } - - $status = false; - $warnings = []; - $loginurl = ''; - - if (!$oauthclient->is_logged_in()) { - $loginurl = $oauthclient->get_login_url()->out(false); - } else { - $status = true; - } - - return [ - 'status' => $status, - 'loginurl' => $loginurl, - 'warnings' => $warnings, - ]; - } - - /** - * Describes the data returned from the external function. - * - * @return external_single_structure - * @since Moodle 4.2 - */ - public static function execute_returns(): external_single_structure { - return new external_single_structure([ - 'loginurl' => new external_value(PARAM_RAW, 'Login url'), - 'status' => new external_value(PARAM_BOOL, 'status: true if success'), - 'warnings' => new external_warnings(), - ]); - } - - /** - * Handle return error. - * - * @param int $itemid Item id - * @param string $warningcode Warning code - * @param string $message Message - * @return array - */ - protected static function return_errors(int $itemid, string $warningcode, string $message): array { - $warnings[] = [ - 'item' => $itemid, - 'warningcode' => $warningcode, - 'message' => $message, - ]; - - return [ - 'status' => false, - 'loginurl' => '', - 'warnings' => $warnings, - ]; - } -} diff --git a/public/lib/classes/external/moodlenet_get_share_info_activity.php b/public/lib/classes/external/moodlenet_get_share_info_activity.php deleted file mode 100644 index c649e75d94f..00000000000 --- a/public/lib/classes/external/moodlenet_get_share_info_activity.php +++ /dev/null @@ -1,152 +0,0 @@ -. - -namespace core\external; - -use context_course; -use core\moodlenet\utilities; -use core\oauth2\api; -use core_external\external_api; -use core_external\external_function_parameters; -use core_external\external_single_structure; -use core_external\external_value; -use core_external\external_warnings; - -/** - * The external API to het the activity information for MoodleNet sharing. - * - * @package core - * @copyright 2023 Huong Nguyen - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class moodlenet_get_share_info_activity extends external_api { - - /** - * Returns description of parameters. - * - * @return external_function_parameters - * @since Moodle 4.2 - */ - public static function execute_parameters(): external_function_parameters { - return new external_function_parameters([ - 'cmid' => new external_value(PARAM_INT, 'The cmid of the activity', VALUE_REQUIRED), - ]); - } - - /** - * External function to get the activity information. - * - * @param int $cmid The course module id. - * @return array - * @since Moodle 4.2 - */ - public static function execute(int $cmid): array { - global $CFG, $USER; - - [ - 'cmid' => $cmid - ] = self::validate_parameters(self::execute_parameters(), [ - 'cmid' => $cmid - ]); - - // Get course module. - $coursemodule = get_coursemodule_from_id(false, $cmid); - if (!$coursemodule) { - return self::return_errors($cmid, 'errorgettingactivityinformation', get_string('invalidcoursemodule', 'error')); - } - - // Get course. - $course = get_course($coursemodule->course); - - // Check capability. - $coursecontext = context_course::instance($course->id); - $usercanshare = utilities::can_user_share($coursecontext, $USER->id); - if (!$usercanshare) { - return self::return_errors($cmid, 'errorpermission', - get_string('nopermissions', 'error', get_string('moodlenet:sharetomoodlenet', 'moodle'))); - } - - $warnings = []; - $supporturl = utilities::get_support_url(); - $issuerid = get_config('moodlenet', 'oauthservice'); - - if (empty($issuerid)) { - return self::return_errors(0, 'errorissuernotset', get_string('moodlenet:issuerisnotset', 'moodle')); - } - - // Get the issuer. - $issuer = api::get_issuer($issuerid); - // Validate the issuer and check if it is enabled or not. - if (!utilities::is_valid_instance($issuer)) { - return self::return_errors($issuerid, 'errorissuernotenabled', get_string('moodlenet:issuerisnotenabled', 'moodle')); - } - - return [ - 'status' => true, - 'name' => $coursemodule->name, - 'type' => get_string('modulename', $coursemodule->modname), - 'server' => $issuer->get_display_name(), - 'supportpageurl' => $supporturl, - 'issuerid' => $issuerid, - 'warnings' => $warnings - ]; - } - - /** - * Describes the data returned from the external function. - * - * @return external_single_structure - * @since Moodle 4.2 - */ - public static function execute_returns(): external_single_structure { - return new external_single_structure([ - 'name' => new external_value(PARAM_TEXT, 'Activity name'), - 'type' => new external_value(PARAM_TEXT, 'Activity type'), - 'server' => new external_value(PARAM_TEXT, 'MoodleNet server'), - 'supportpageurl' => new external_value(PARAM_URL, 'Support page URL'), - 'issuerid' => new external_value(PARAM_INT, 'MoodleNet issuer id'), - 'status' => new external_value(PARAM_BOOL, 'status: true if success'), - 'warnings' => new external_warnings() - ]); - } - - /** - * Handle return error. - * - * @param int $itemid Item id. - * @param string $warningcode Warning code. - * @param string $message Message. - * @param int $issuerid Issuer id. - * @return array - */ - protected static function return_errors(int $itemid, string $warningcode, string $message, int $issuerid = 0): array { - $warnings[] = [ - 'item' => $itemid, - 'warningcode' => $warningcode, - 'message' => $message - ]; - - return [ - 'status' => false, - 'name' => '', - 'type' => '', - 'server' => '', - 'supportpageurl' => '', - 'issuerid' => $issuerid, - 'warnings' => $warnings - ]; - } -} diff --git a/public/lib/classes/external/moodlenet_get_shared_course_info.php b/public/lib/classes/external/moodlenet_get_shared_course_info.php deleted file mode 100644 index 656c9324d09..00000000000 --- a/public/lib/classes/external/moodlenet_get_shared_course_info.php +++ /dev/null @@ -1,143 +0,0 @@ -. - -namespace core\external; - -use context_course; -use core\moodlenet\utilities; -use core\oauth2\api; -use core_external\external_api; -use core_external\external_function_parameters; -use core_external\external_single_structure; -use core_external\external_value; -use core_external\external_warnings; - -/** - * The external API to get MoodleNet information about the course to be shared. - * - * @package core - * @copyright 2023 Safat Shahin - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - * @since Moodle 4.3 - */ -class moodlenet_get_shared_course_info extends external_api { - - /** - * Returns description of parameters. - * - * @return external_function_parameters - */ - public static function execute_parameters(): external_function_parameters { - return new external_function_parameters([ - 'courseid' => new external_value(PARAM_INT, 'The course id', VALUE_REQUIRED), - ]); - } - - /** - * External function to get the course information. - * - * @param int $courseid The course id - * @return array - */ - public static function execute(int $courseid): array { - global $USER; - - [ - 'courseid' => $courseid - ] = self::validate_parameters(self::execute_parameters(), [ - 'courseid' => $courseid - ]); - - // Get course. - $course = get_course($courseid); - - // Check capability. - $coursecontext = context_course::instance($course->id); - if (!utilities::can_user_share($coursecontext, $USER->id, 'course')) { - return self::return_errors($courseid, 'errorpermission', - get_string('nopermissions', 'error', get_string('moodlenet:sharetomoodlenet', 'moodle'))); - } - - $warnings = []; - $supporturl = utilities::get_support_url(); - $issuerid = get_config('moodlenet', 'oauthservice'); - - if (empty($issuerid)) { - return self::return_errors(0, 'errorissuernotset', get_string('moodlenet:issuerisnotset', 'moodle')); - } - - // Get the issuer. - $issuer = api::get_issuer($issuerid); - // Validate the issuer and check if it is enabled or not. - if (!utilities::is_valid_instance($issuer)) { - return self::return_errors($issuerid, 'errorissuernotenabled', get_string('moodlenet:issuerisnotenabled', 'moodle')); - } - - return [ - 'status' => true, - 'name' => $course->fullname, - 'type' => get_string('course'), - 'server' => $issuer->get_display_name(), - 'supportpageurl' => $supporturl, - 'issuerid' => $issuerid, - 'warnings' => $warnings - ]; - } - - /** - * Describes the data returned from the external function. - * - * @return external_single_structure - */ - public static function execute_returns(): external_single_structure { - return new external_single_structure([ - 'name' => new external_value(PARAM_TEXT, 'Course short name'), - 'type' => new external_value(PARAM_TEXT, 'Course type'), - 'server' => new external_value(PARAM_TEXT, 'MoodleNet server'), - 'supportpageurl' => new external_value(PARAM_URL, 'Support page URL'), - 'issuerid' => new external_value(PARAM_INT, 'MoodleNet issuer id'), - 'status' => new external_value(PARAM_BOOL, 'status: true if success'), - 'warnings' => new external_warnings() - ]); - } - - /** - * Handle return error. - * - * @param int $itemid Item id. - * @param string $warningcode Warning code. - * @param string $message Message. - * @param int $issuerid Issuer id. - * @return array - */ - protected static function return_errors(int $itemid, string $warningcode, string $message, int $issuerid = 0): array { - $warnings[] = [ - 'item' => $itemid, - 'warningcode' => $warningcode, - 'message' => $message - ]; - - return [ - 'status' => false, - 'name' => '', - 'type' => '', - 'server' => '', - 'supportpageurl' => '', - 'issuerid' => $issuerid, - 'warnings' => $warnings - ]; - } -} diff --git a/public/lib/classes/external/moodlenet_send_activity.php b/public/lib/classes/external/moodlenet_send_activity.php deleted file mode 100644 index 33320f27570..00000000000 --- a/public/lib/classes/external/moodlenet_send_activity.php +++ /dev/null @@ -1,185 +0,0 @@ -. - -namespace core\external; - -use context_course; -use core\http_client; -use core\moodlenet\activity_sender; -use core\moodlenet\moodlenet_client; -use core\moodlenet\utilities; -use core\moodlenet\share_recorder; -use core\oauth2\api; -use core_external\external_api; -use core_external\external_function_parameters; -use core_external\external_single_structure; -use core_external\external_value; -use core_external\external_warnings; -use moodle_url; - -/** - * The external API to send activity to MoodleNet. - * - * @package core - * @copyright 2023 Huong Nguyen - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class moodlenet_send_activity extends external_api { - - /** - * Describes the parameters for sending the activity. - * - * @return external_function_parameters - * @since Moodle 4.2 - */ - public static function execute_parameters(): external_function_parameters { - return new external_function_parameters([ - 'issuerid' => new external_value(PARAM_INT, 'OAuth 2 issuer ID', VALUE_REQUIRED), - 'cmid' => new external_value(PARAM_INT, 'Course module ID', VALUE_REQUIRED), - 'shareformat' => new external_value(PARAM_INT, 'Share format', VALUE_REQUIRED), - ]); - } - - /** - * External function to send the activity to MoodleNet. - * - * @param int $issuerid The MoodleNet OAuth 2 issuer ID - * @param int $cmid The course module ID of the activity that being shared - * @param int $shareformat The share format being used, as defined by \core\moodlenet\activity_sender - * @return array - * @since Moodle 4.2 - */ - public static function execute(int $issuerid, int $cmid, int $shareformat): array { - global $CFG, $USER; - - [ - 'issuerid' => $issuerid, - 'cmid' => $cmid, - 'shareformat' => $shareformat, - ] = self::validate_parameters(self::execute_parameters(), [ - 'issuerid' => $issuerid, - 'cmid' => $cmid, - 'shareformat' => $shareformat, - ]); - - // Check capability. - [$course] = get_course_and_cm_from_cmid($cmid); - $coursecontext = context_course::instance($course->id); - $usercanshare = utilities::can_user_share($coursecontext, $USER->id); - if (!$usercanshare) { - return self::return_errors($cmid, 'errorpermission', - get_string('nopermissions', 'error', get_string('moodlenet:sharetomoodlenet', 'moodle'))); - } - - // Check format. - if (!in_array($shareformat, [activity_sender::SHARE_FORMAT_BACKUP])) { - return self::return_errors($shareformat, 'errorinvalidformat', get_string('invalidparameter', 'debug')); - } - - // Get the issuer. - $issuer = api::get_issuer($issuerid); - // Validate the issuer and check if it is enabled or not. - if (!utilities::is_valid_instance($issuer)) { - return self::return_errors($issuerid, 'errorissuernotenabled', get_string('invalidparameter', 'debug')); - } - - // Get the OAuth Client. - if (!$oauthclient = api::get_user_oauth_client( - $issuer, - new moodle_url($CFG->wwwroot), - moodlenet_client::API_SCOPE_CREATE_RESOURCE - )) { - return self::return_errors($issuerid, 'erroroauthclient', get_string('invalidparameter', 'debug')); - } - - // Check login state. - if (!$oauthclient->is_logged_in()) { - return self::return_errors($issuerid, 'erroroauthclient', get_string('moodlenet:issuerisnotauthorized', 'moodle')); - } - - // Get the HTTP Client. - $client = new http_client(); - - // Share activity. - try { - // Record activity share progress. - $shareid = share_recorder::insert_share_progress(share_recorder::TYPE_ACTIVITY, $USER->id, $course->id, $cmid); - - $moodlenetclient = new moodlenet_client($client, $oauthclient); - $activitysender = new activity_sender($cmid, $USER->id, $moodlenetclient, $oauthclient, $shareformat); - $result = $activitysender->share_resource(); - if (empty($result['drafturl'])) { - - share_recorder::update_share_progress($shareid, share_recorder::STATUS_ERROR); - - return self::return_errors($result['responsecode'], 'errorsendingactivity', - get_string('moodlenet:cannotconnecttoserver', 'moodle')); - } - } catch (\moodle_exception $e) { - - share_recorder::update_share_progress($shareid, share_recorder::STATUS_ERROR); - - return self::return_errors(0, 'errorsendingactivity', $e->getMessage()); - } - - share_recorder::update_share_progress($shareid, share_recorder::STATUS_SENT, $result['drafturl']); - - return [ - 'status' => true, - 'resourceurl' => $result['drafturl'], - 'warnings' => [], - ]; - } - - /** - * Describes the data returned from the external function. - * - * @return external_single_structure - * @since Moodle 4.2 - */ - public static function execute_returns(): external_single_structure { - return new external_single_structure([ - 'status' => new external_value(PARAM_BOOL, 'Status: true if success'), - // We used PARAM_TEXT instead of PARAM_URL because the URL return from MoodleNet may contain some characters. - // It does not match with PARAM_URL, but the URL still works. - // Since we just show the response resource URL to the user for them to navigate to MoodleNet, it would be safe. - 'resourceurl' => new external_value(PARAM_TEXT, 'Resource URL from MoodleNet'), - 'warnings' => new external_warnings(), - ]); - } - - /** - * Handle return error. - * - * @param int $itemid Item id - * @param string $warningcode Warning code - * @param string $message Message - * @return array - */ - protected static function return_errors(int $itemid, string $warningcode, string $message): array { - $warnings[] = [ - 'item' => $itemid, - 'warningcode' => $warningcode, - 'message' => $message, - ]; - - return [ - 'status' => false, - 'resourceurl' => '', - 'warnings' => $warnings, - ]; - } -} diff --git a/public/lib/classes/external/moodlenet_send_course.php b/public/lib/classes/external/moodlenet_send_course.php deleted file mode 100644 index d625e98ea6e..00000000000 --- a/public/lib/classes/external/moodlenet_send_course.php +++ /dev/null @@ -1,244 +0,0 @@ -. - -namespace core\external; - -use context_course; -use core\http_client; -use core\moodlenet\course_partial_sender; -use core\moodlenet\course_sender; -use core\moodlenet\moodlenet_client; -use core\moodlenet\share_recorder; -use core\moodlenet\utilities; -use core\oauth2\api; -use core_external\external_api; -use core_external\external_function_parameters; -use core_external\external_multiple_structure; -use core_external\external_single_structure; -use core_external\external_value; -use core_external\external_warnings; -use moodle_url; - -/** - * The external API to send course to MoodleNet. - * - * @package core - * @copyright 2023 Safat Shahin - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class moodlenet_send_course extends external_api { - - /** - * Describes the parameters for sending the course. - * - * @return external_function_parameters - */ - public static function execute_parameters(): external_function_parameters { - return new external_function_parameters([ - 'issuerid' => new external_value(PARAM_INT, 'OAuth 2 issuer ID', VALUE_REQUIRED), - 'courseid' => new external_value(PARAM_INT, 'Course ID', VALUE_REQUIRED), - 'shareformat' => new external_value(PARAM_INT, 'Share format', VALUE_REQUIRED), - 'cmids' => new external_multiple_structure( - new external_value(PARAM_INT, 'Course module id', VALUE_DEFAULT, null, NULL_ALLOWED), - 'List for course module ids', VALUE_DEFAULT, [] - ), - ]); - } - - /** - * External function to send the course to MoodleNet. - * - * @param int $issuerid The MoodleNet OAuth 2 issuer ID - * @param int $courseid The course ID - * @param int $shareformat The share format being used, as defined by \core\moodlenet\course_sender - * @param array $cmids The course module ids - * @return array - */ - public static function execute( - int $issuerid, - int $courseid, - int $shareformat, - array $cmids = [], - ): array { - global $CFG, $USER; - - [ - 'issuerid' => $issuerid, - 'courseid' => $courseid, - 'shareformat' => $shareformat, - 'cmids' => $cmids, - ] = self::validate_parameters(self::execute_parameters(), [ - 'issuerid' => $issuerid, - 'courseid' => $courseid, - 'shareformat' => $shareformat, - 'cmids' => $cmids, - ]); - - // Partial sharing check. - $ispartialsharing = count($cmids) > 0; - - // Check capability. - $coursecontext = context_course::instance($courseid); - $usercanshare = utilities::can_user_share($coursecontext, $USER->id, 'course'); - if (!$usercanshare) { - return self::return_errors( - $courseid, - 'errorpermission', - get_string('nopermissions', 'error', get_string('moodlenet:sharetomoodlenet', 'moodle')) - ); - } - - // Check format. - if ($shareformat !== course_sender::SHARE_FORMAT_BACKUP) { - return self::return_errors( - $shareformat, - 'errorinvalidformat', - get_string('invalidparameter', 'debug') - ); - } - - if ($ispartialsharing) { - // Check course modules in the course. - $modinfo = get_fast_modinfo($courseid); - $cms = $modinfo->get_cms(); - foreach ($cmids as $cmid) { - if (!array_key_exists($cmid, $cms)) { - return self::return_errors( - $cmid, - 'errorinvalidcmids', - get_string('invalidparameter', 'debug') - ); - } - } - } - - // Get the issuer. - $issuer = api::get_issuer($issuerid); - // Validate the issuer and check if it is enabled or not. - if (!utilities::is_valid_instance($issuer)) { - return self::return_errors( - $issuerid, - 'errorissuernotenabled', - get_string('invalidparameter', 'debug') - ); - } - - // Get the OAuth Client. - if (!$oauthclient = api::get_user_oauth_client( - $issuer, - new moodle_url($CFG->wwwroot), - moodlenet_client::API_SCOPE_CREATE_RESOURCE - )) { - return self::return_errors( - $issuerid, - 'erroroauthclient', - get_string('invalidparameter', 'debug') - ); - } - - // Check login state. - if (!$oauthclient->is_logged_in()) { - return self::return_errors( - $issuerid, - 'erroroauthclient', - get_string('moodlenet:issuerisnotauthorized', 'moodle') - ); - } - - // Get the HTTP Client. - $client = new http_client(); - - // Share course. - try { - // Record course share progress. - $shareid = share_recorder::insert_share_progress(share_recorder::TYPE_COURSE, $USER->id, $courseid); - - $moodlenetclient = new moodlenet_client($client, $oauthclient); - if ($ispartialsharing) { - $coursesender = new course_partial_sender($courseid, $USER->id, $moodlenetclient, - $oauthclient, $cmids, $shareformat); - } else { - $coursesender = new course_sender($courseid, $USER->id, $moodlenetclient, $oauthclient, $shareformat); - } - $result = $coursesender->share_resource(); - if (empty($result['drafturl'])) { - - share_recorder::update_share_progress($shareid, share_recorder::STATUS_ERROR); - - return self::return_errors( - $result['responsecode'], - 'errorsendingcourse', - get_string('moodlenet:cannotconnecttoserver', 'moodle') - ); - } - } catch (\moodle_exception | \JsonException $e) { - - share_recorder::update_share_progress($shareid, share_recorder::STATUS_ERROR); - - return self::return_errors( - 0, - 'errorsendingcourse', - $e->getMessage() - ); - } - - share_recorder::update_share_progress($shareid, share_recorder::STATUS_SENT, $result['drafturl']); - - return [ - 'status' => true, - 'resourceurl' => $result['drafturl'], - 'warnings' => [], - ]; - } - - /** - * Describes the data returned from the external function. - * - * @return external_single_structure - */ - public static function execute_returns(): external_single_structure { - return new external_single_structure([ - 'status' => new external_value(PARAM_BOOL, 'Status: true if success'), - // We used PARAM_TEXT instead of PARAM_URL because the URL return from MoodleNet may contain some characters. - // It does not match with PARAM_URL, but the URL still works. - // Since we just show the response resource URL to the user for them to navigate to MoodleNet, it would be safe. - 'resourceurl' => new external_value(PARAM_TEXT, 'Resource URL from MoodleNet'), - 'warnings' => new external_warnings(), - ]); - } - - /** - * Handle return error. - * - * @param int $itemid Item id - * @param string $warningcode Warning code - * @param string $message Message - * @return array - */ - protected static function return_errors(int $itemid, string $warningcode, string $message): array { - $warnings[] = [ - 'item' => $itemid, - 'warningcode' => $warningcode, - 'message' => $message, - ]; - - return [ - 'status' => false, - 'resourceurl' => '', - 'warnings' => $warnings, - ]; - } -} diff --git a/public/lib/classes/moodlenet/activity_packager.php b/public/lib/classes/moodlenet/activity_packager.php deleted file mode 100644 index 23e4fe30091..00000000000 --- a/public/lib/classes/moodlenet/activity_packager.php +++ /dev/null @@ -1,69 +0,0 @@ -. - -namespace core\moodlenet; - -use backup; -use backup_controller; -use cm_info; - -defined('MOODLE_INTERNAL') || die(); - -require_once($CFG->dirroot . '/backup/util/includes/backup_includes.php'); - -/** - * Packager to prepare appropriate backup of an activity to share to MoodleNet. - * - * @package core - * @copyright 2023 Raquel Ortega - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class activity_packager extends resource_packager { - - /** - * Constructor. - * - * @param cm_info $cminfo context module information about the resource being packaged. - * @param int $userid The ID of the user performing the packaging. - */ - public function __construct( - cm_info $cminfo, - int $userid, - ) { - // Check backup/restore support. - if (!plugin_supports('mod', $cminfo->modname , FEATURE_BACKUP_MOODLE2)) { - throw new \coding_exception("Cannot backup module $cminfo->modname. This module doesn't support the backup feature."); - } - - parent::__construct($cminfo, $userid, $cminfo->modname); - } - - /** - * Get the backup controller for the activity. - * - * @return backup_controller the backup controller for the activity. - */ - protected function get_backup_controller(): backup_controller { - return new backup_controller( - backup::TYPE_1ACTIVITY, - $this->cminfo->id, - backup::FORMAT_MOODLE, - backup::INTERACTIVE_NO, - backup::MODE_GENERAL, - $this->userid - ); - } -} diff --git a/public/lib/classes/moodlenet/activity_sender.php b/public/lib/classes/moodlenet/activity_sender.php deleted file mode 100644 index 93e575f1955..00000000000 --- a/public/lib/classes/moodlenet/activity_sender.php +++ /dev/null @@ -1,176 +0,0 @@ -. - -namespace core\moodlenet; - -use cm_info; -use core\event\moodlenet_resource_exported; -use core\oauth2\client; -use moodle_exception; -use stored_file; - -/** - * API for sharing Moodle LMS activities to MoodleNet instances. - * - * @package core - * @copyright 2023 Michael Hawkins - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class activity_sender extends resource_sender { - - /** - * @var cm_info The context module info object for the activity being shared. - */ - protected cm_info $cminfo; - - /** - * Class constructor. - * - * @param int $cmid The course module ID of the activity being shared - * @param int $userid The user ID who is sharing the activity - * @param moodlenet_client $moodlenetclient The moodlenet_client object used to perform the share - * @param client $oauthclient The OAuth 2 client for the MoodleNet instance - * @param int $shareformat The data format to share in. Defaults to a Moodle backup (SHARE_FORMAT_BACKUP) - */ - public function __construct( - int $cmid, - protected int $userid, - protected moodlenet_client $moodlenetclient, - protected client $oauthclient, - protected int $shareformat = self::SHARE_FORMAT_BACKUP, - ) { - parent::__construct($cmid, $userid, $moodlenetclient, $oauthclient, $shareformat); - [$this->course, $this->cminfo] = get_course_and_cm_from_cmid($cmid); - $this->packager = new activity_packager($this->cminfo, $this->userid); - } - - /** - * Share an activity/resource to MoodleNet. - * - * @return array The HTTP response code from MoodleNet and the MoodleNet draft resource URL (URL empty string on fail). - * Format: ['responsecode' => 201, 'drafturl' => 'https://draft.mnurl/here'] - */ - public function share_resource(): array { - $accesstoken = ''; - $resourceurl = ''; - $issuer = $this->oauthclient->get_issuer(); - - // Check user can share to the requested MoodleNet instance. - $coursecontext = \core\context\course::instance($this->course->id); - $usercanshare = utilities::can_user_share($coursecontext, $this->userid); - - if ($usercanshare && utilities::is_valid_instance($issuer) && $this->oauthclient->is_logged_in()) { - $accesstoken = $this->oauthclient->get_accesstoken()->token; - } - - // Throw an exception if the user is not currently set up to be able to share to MoodleNet. - if (!$accesstoken) { - throw new moodle_exception('moodlenet:usernotconfigured'); - } - - // Attempt to prepare and send the resource if validation has passed and we have an OAuth 2 token. - - // Prepare file in requested format. - $filedata = $this->prepare_share_contents(); - - // If we have successfully prepared a file to share of permitted size, share it to MoodleNet. - if (!empty($filedata)) { - // Avoid sending a file larger than the defined limit. - $filesize = $filedata->get_filesize(); - if ($filesize > self::MAX_FILESIZE) { - $filedata->delete(); - throw new moodle_exception('moodlenet:sharefilesizelimitexceeded', 'core', '', [ - 'filesize' => $filesize, - 'filesizelimit' => self::MAX_FILESIZE, - ]); - } - - // MoodleNet only accept plaintext descriptions. - $resourcedescription = $this->get_resource_description($coursecontext); - - $response = $this->moodlenetclient->create_resource_from_stored_file( - $filedata, - $this->cminfo->name, - $resourcedescription, - ); - $responsecode = $response->getStatusCode(); - - $responsebody = json_decode($response->getBody()); - $resourceurl = $responsebody->homepage ?? ''; - - // Delete the generated file now it is no longer required. - // (It has either been sent, or failed - retries not currently supported). - $filedata->delete(); - } - - // Log every attempt to share (and whether or not it was successful). - $this->log_event($coursecontext, $this->cminfo->id, $resourceurl, $responsecode); - - return [ - 'responsecode' => $responsecode, - 'drafturl' => $resourceurl, - ]; - } - - /** - * Log an event to the admin logs for an outbound share attempt. - * - * @param \context $coursecontext The course context being shared from. - * @param int $cmid The CMID of the activity being shared. - * @param string $resourceurl The URL of the draft resource if it was created. - * @param int $responsecode The HTTP response code describing the outcome of the attempt. - * @return void - */ - protected function log_event( - \core\context $coursecontext, - int $cmid, - string $resourceurl, - int $responsecode, - ): void { - $event = moodlenet_resource_exported::create([ - 'context' => $coursecontext, - 'other' => [ - 'cmids' => [$cmid], - 'resourceurl' => $resourceurl, - 'success' => ($responsecode == 201), - ], - ]); - $event->trigger(); - } - - /** - * Fetch the description for the resource being created, in a supported text format. - * - * @param \context $coursecontext The course context being shared from. - * @return string Converted activity description. - */ - protected function get_resource_description( - \context $coursecontext, - ): string { - global $PAGE, $DB; - // We need to set the page context here because content_to_text and format_text will need the page context to work. - $PAGE->set_context($coursecontext); - - $intro = $DB->get_record($this->cminfo->modname, ['id' => $this->cminfo->instance], 'intro, introformat', MUST_EXIST); - $processeddescription = strip_tags($intro->intro); - $processeddescription = content_to_text(format_text( - $processeddescription, - $intro->introformat, - ), $intro->introformat); - - return $processeddescription; - } -} diff --git a/public/lib/classes/moodlenet/course_packager.php b/public/lib/classes/moodlenet/course_packager.php deleted file mode 100644 index 713afa74ebe..00000000000 --- a/public/lib/classes/moodlenet/course_packager.php +++ /dev/null @@ -1,64 +0,0 @@ -. - -namespace core\moodlenet; - -use backup; -use backup_controller; -use stdClass; - -defined('MOODLE_INTERNAL') || die(); - -require_once($CFG->dirroot . '/backup/util/includes/backup_includes.php'); - -/** - * Packager to prepare appropriate backup of a course to share to MoodleNet. - * - * @package core - * @copyright 2023 Safat Shahin - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class course_packager extends resource_packager { - - /** - * Constructor for course packager. - * - * @param stdClass $course The course to package - * @param int $userid The ID of the user performing the packaging - */ - public function __construct( - stdClass $course, - int $userid, - ) { - parent::__construct($course, $userid, $course->shortname); - } - - /** - * Get the backup controller for the course. - * - * @return backup_controller the backup controller for the course. - */ - protected function get_backup_controller(): backup_controller { - return new backup_controller( - backup::TYPE_1COURSE, - $this->course->id, - backup::FORMAT_MOODLE, - backup::INTERACTIVE_NO, - backup::MODE_GENERAL, - $this->userid, - ); - } -} diff --git a/public/lib/classes/moodlenet/course_partial_packager.php b/public/lib/classes/moodlenet/course_partial_packager.php deleted file mode 100644 index f722199bf56..00000000000 --- a/public/lib/classes/moodlenet/course_partial_packager.php +++ /dev/null @@ -1,99 +0,0 @@ -. - -namespace core\moodlenet; - -use backup_activity_task; -use backup_controller; -use stdClass; -use stored_file; - -/** - * Packager to prepare appropriate backup of a number of activities in a course to share to MoodleNet. - * - * @package core - * @copyright 2023 Huong Nguyen - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class course_partial_packager extends course_packager { - - /** - * @var int[] $cmids List of course module ids of selected activities. - */ - protected array $cmids; - - /** - * Constructor for course partial packager. - * - * @param stdClass $course The course to package - * @param array $cmids List of course module id of selected activities. - * @param int $userid The ID of the user performing the packaging - */ - public function __construct( - stdClass $course, - array $cmids, - int $userid, - ) { - $this->cmids = $cmids; - parent::__construct($course, $userid); - } - - /** - * Package the resource identified by resource id into a new stored_file. - * - * @param backup_controller $controller The backup controller. - * @return stored_file - */ - protected function package(backup_controller $controller): stored_file { - $this->remove_unselected_activities($controller); - return parent::package($controller); - } - - /** - * Remove unselected activities in the course backup. - * - * @param backup_controller $controller The backup controller. - */ - protected function remove_unselected_activities(backup_controller $controller): void { - foreach ($this->get_all_activity_tasks($controller) as $task) { - foreach ($task->get_settings() as $setting) { - if (in_array($task->get_moduleid(), $this->cmids) && - str_contains($setting->get_name(), '_included') !== false) { - $setting->set_value(1); - } else { - $setting->set_value(0); - } - } - } - } - - /** - * Get all the activity tasks in the controller. - * - * @param backup_controller $controller The backup controller. - * @return backup_activity_task[] Array of activity tasks. - */ - protected function get_all_activity_tasks(backup_controller $controller): array { - $tasks = []; - foreach ($controller->get_plan()->get_tasks() as $task) { - if (! $task instanceof backup_activity_task) { // Only for activity tasks. - continue; - } - $tasks[] = $task; - } - return $tasks; - } -} diff --git a/public/lib/classes/moodlenet/course_partial_sender.php b/public/lib/classes/moodlenet/course_partial_sender.php deleted file mode 100644 index d29b066b6e2..00000000000 --- a/public/lib/classes/moodlenet/course_partial_sender.php +++ /dev/null @@ -1,100 +0,0 @@ -. - -namespace core\moodlenet; - -use core\event\moodlenet_resource_exported; -use core\oauth2\client; -use moodle_exception; - -/** - * API for sharing a number of Moodle LMS activities as a course backup to MoodleNet instances. - * - * @package core - * @copyright 2023 Huong Nguyen - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class course_partial_sender extends course_sender { - - /** - * Constructor for course sender. - * - * @param int $courseid The course ID of the course being shared - * @param int $userid The user ID who is sharing the activity - * @param moodlenet_client $moodlenetclient The moodlenet_client object used to perform the share - * @param client $oauthclient The OAuth 2 client for the MoodleNet instance - * @param int $shareformat The data format to share in. Defaults to a Moodle backup (SHARE_FORMAT_BACKUP) - */ - public function __construct( - int $courseid, - protected int $userid, - protected moodlenet_client $moodlenetclient, - protected client $oauthclient, - protected array $cmids, - protected int $shareformat = self::SHARE_FORMAT_BACKUP, - ) { - parent::__construct($courseid, $userid, $moodlenetclient, $oauthclient, $shareformat); - $this->validate_course_module_ids($this->course, $this->cmids); - $this->packager = new course_partial_packager($this->course, $this->cmids, $this->userid); - } - - /** - * Log an event to the admin logs for an outbound share attempt. - * - * @param string $resourceurl The URL of the draft resource if it was created - * @param int $responsecode The HTTP response code describing the outcome of the attempt - * @return void - */ - protected function log_event( - string $resourceurl, - int $responsecode, - ): void { - $event = moodlenet_resource_exported::create([ - 'context' => $this->coursecontext, - 'other' => [ - 'cmids' => $this->cmids, - 'courseid' => [$this->course->id], - 'resourceurl' => $resourceurl, - 'success' => ($responsecode === 201), - ], - ]); - $event->trigger(); - } - - /** - * Validate the course module ids. - * - * @param \stdClass $course Course object - * @param array $cmids List of course module ids to check - * @return void - */ - protected function validate_course_module_ids( - \stdClass $course, - array $cmids, - ): void { - if (empty($cmids)) { - throw new moodle_exception('invalidcoursemodule'); - } - $modinfo = get_fast_modinfo($course); - $cms = $modinfo->get_cms(); - foreach ($cmids as $cmid) { - if (!array_key_exists($cmid, $cms)) { - throw new moodle_exception('invalidcoursemodule'); - } - } - } - -} diff --git a/public/lib/classes/moodlenet/course_sender.php b/public/lib/classes/moodlenet/course_sender.php deleted file mode 100644 index 40885ccf17f..00000000000 --- a/public/lib/classes/moodlenet/course_sender.php +++ /dev/null @@ -1,180 +0,0 @@ -. - -namespace core\moodlenet; - -use core\event\moodlenet_resource_exported; -use core\oauth2\client; -use moodle_exception; -use stored_file; - -/** - * API for sharing Moodle LMS courses to MoodleNet instances. - * - * @package core - * @copyright 2023 Safat Shahin - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class course_sender extends resource_sender { - - /** - * @var \core\context\course|false The course context. - */ - protected \core\context\course|false $coursecontext; - - /** - * Constructor for course sender. - * - * @param int $courseid The course ID of the course being shared - * @param int $userid The user ID who is sharing the activity - * @param moodlenet_client $moodlenetclient The moodlenet_client object used to perform the share - * @param client $oauthclient The OAuth 2 client for the MoodleNet instance - * @param int $shareformat The data format to share in. Defaults to a Moodle backup (SHARE_FORMAT_BACKUP) - */ - public function __construct( - int $courseid, - protected int $userid, - protected moodlenet_client $moodlenetclient, - protected client $oauthclient, - protected int $shareformat = self::SHARE_FORMAT_BACKUP, - ) { - parent::__construct($courseid, $userid, $moodlenetclient, $oauthclient, $shareformat); - $this->course = get_course($courseid); - $this->coursecontext = \core\context\course::instance($courseid); - $this->packager = new course_packager($this->course, $this->userid); - } - - /** - * Share a course to MoodleNet. - * - * @return array The HTTP response code from MoodleNet and the MoodleNet draft resource URL (URL empty string on fail). - * Format: ['responsecode' => 201, 'drafturl' => 'https://draft.mnurl/here'] - */ - public function share_resource(): array { - - $accesstoken = ''; - $issuer = $this->oauthclient->get_issuer(); - - // Check user can share to the requested MoodleNet instance. - $usercanshare = utilities::can_user_share($this->coursecontext, $this->userid, 'course'); - - if ($usercanshare && utilities::is_valid_instance($issuer) && $this->oauthclient->is_logged_in()) { - $accesstoken = $this->oauthclient->get_accesstoken()->token; - } - - // Throw an exception if the user is not currently set up to be able to share to MoodleNet. - if (!$accesstoken) { - throw new moodle_exception('moodlenet:usernotconfigured'); - } - - // Attempt to prepare and send the resource if validation has passed and we have an OAuth 2 token. - - // Prepare file in requested format. - $filedata = $this->prepare_share_contents(); - - // Avoid sending a file larger than the defined limit. - $filesize = $filedata->get_filesize(); - if ($filesize > self::MAX_FILESIZE) { - $filedata->delete(); - throw new moodle_exception('moodlenet:sharefilesizelimitexceeded', 'core', '', [ - 'filesize' => $filesize, - 'filesizelimit' => self::MAX_FILESIZE, - ]); - } - - // MoodleNet only accept plaintext descriptions. - $resourcedescription = $this->get_resource_description(); - - $response = $this->moodlenetclient->create_resource_from_stored_file( - $filedata, - $this->course->fullname, - $resourcedescription, - ); - $responsecode = $response->getStatusCode(); - - $responsebody = json_decode($response->getBody(), false, 512, JSON_THROW_ON_ERROR); - $resourceurl = $responsebody->homepage ?? ''; - - // Delete the generated file now it is no longer required. - // (It has either been sent, or failed - retries not currently supported). - $filedata->delete(); - - // Log every attempt to share (and whether it was successful). - $this->log_event($resourceurl, $responsecode); - - return [ - 'responsecode' => $responsecode, - 'drafturl' => $resourceurl, - ]; - } - - /** - * Log an event to the admin logs for an outbound share attempt. - * - * @param string $resourceurl The URL of the draft resource if it was created - * @param int $responsecode The HTTP response code describing the outcome of the attempt - * @return void - */ - protected function log_event( - string $resourceurl, - int $responsecode, - ): void { - $event = moodlenet_resource_exported::create([ - 'context' => $this->coursecontext, - 'other' => [ - 'courseid' => [$this->course->id], - 'resourceurl' => $resourceurl, - 'success' => ($responsecode === 201), - ], - ]); - $event->trigger(); - } - - /** - * Return the list of supported share formats. - * - * @return array Array of supported share format values. - */ - protected static function get_allowed_share_formats(): array { - return [ - self::SHARE_FORMAT_BACKUP, - ]; - } - - /** - * Fetch the description for the resource being created, in a supported text format. - * - * @return string Converted course description. - */ - protected function get_resource_description(): string { - global $PAGE; - - // We need to set the page context here because content_to_text and format_text will need the page context to work. - $PAGE->set_context($this->coursecontext); - - $processeddescription = strip_tags($this->course->summary); - $processeddescription = content_to_text - ( - format_text( - $processeddescription, - $this->course->summaryformat, - ), - $this->course->summaryformat - ); - - return $processeddescription; - } -} diff --git a/public/lib/classes/moodlenet/moodlenet_client.php b/public/lib/classes/moodlenet/moodlenet_client.php deleted file mode 100644 index 8fe1e4ee7b7..00000000000 --- a/public/lib/classes/moodlenet/moodlenet_client.php +++ /dev/null @@ -1,139 +0,0 @@ -. - -namespace core\moodlenet; - -use core\http_client; -use core\oauth2\client; -use stored_file; -use Psr\Http\Message\ResponseInterface; -use Psr\Http\Message\StreamInterface; - -/** - * MoodleNet client which handles direct outbound communication with MoodleNet instances. - * - * @package core - * @copyright 2023 Michael Hawkins - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class moodlenet_client { - /** - * @var string MoodleNet resource creation endpoint URI. - */ - protected const API_CREATE_RESOURCE_URI = '/.pkg/@moodlenet/ed-resource/basic/v1/create'; - - /** - * @var string MoodleNet scope for creating resources. - */ - public const API_SCOPE_CREATE_RESOURCE = '@moodlenet/ed-resource:write.own'; - - - /** - * Constructor. - * - * @param http_client $httpclient The httpclient object being used to perform the share. - * @param client $oauthclient The OAuth 2 client for the MoodleNet site being shared to. - */ - public function __construct( - protected http_client $httpclient, - protected client $oauthclient, - ) { - // All properties promoted, nothing further required. - } - - /** - * Create a resource on MoodleNet which includes a file. - * - * @param stored_file $file The file data to send to MoodleNet. - * @param string $resourcename The name of the resource being shared. - * @param string $resourcedescription A description of the resource being shared. - * @return \Psr\Http\Message\ResponseInterface The HTTP client response from MoodleNet. - */ - public function create_resource_from_stored_file( - stored_file $file, - string $resourcename, - string $resourcedescription, - ): ResponseInterface { - // This may take a long time if a lot of data is being shared. - \core_php_time_limit::raise(); - - $moodleneturl = $this->oauthclient->get_issuer()->get('baseurl'); - $apiurl = rtrim($moodleneturl, '/') . self::API_CREATE_RESOURCE_URI; - $stream = $file->get_psr_stream(); - - $requestdata = $this->prepare_file_share_request_data( - $file->get_filename(), - $file->get_mimetype(), - $stream, - $resourcename, - $resourcedescription, - ); - - try { - $response = $this->httpclient->request('POST', $apiurl, $requestdata); - } finally { - $stream->close(); // Always close the request stream ASAP. Or it will remain open till shutdown/destruct. - } - - return $response; - } - - /** - * Prepare the request data required for sharing a file to MoodleNet. - * This creates an array in the format used by \core\httpclient options to send a multipart request. - * - * @param string $filename Name of the file being shared. - * @param string $mimetype Mime type of the file being shared. - * @param StreamInterface $stream Stream of the file being shared. - * @param string $resourcename The name of the resource being shared. - * @param string $resourcedescription A description of the resource being shared. - * @return array Data in the format required to send a file to MoodleNet using \core\httpclient. - */ - protected function prepare_file_share_request_data( - string $filename, - string $mimetype, - StreamInterface $stream, - string $resourcename, - string $resourcedescription, - ): array { - return [ - 'headers' => [ - 'Authorization' => 'Bearer ' . $this->oauthclient->get_accesstoken()->token, - ], - 'multipart' => [ - [ - 'name' => 'metadata', - 'contents' => json_encode([ - 'name' => $resourcename, - 'description' => $resourcedescription, - ]), - 'headers' => [ - 'Content-Disposition' => 'form-data; name="."', - ], - ], - [ - 'name' => 'filecontents', - 'contents' => $stream, - 'headers' => [ - 'Content-Disposition' => 'form-data; name=".resource"; filename="' . $filename . '"', - 'Content-Type' => $mimetype, - 'Content-Transfer-Encoding' => 'binary', - ], - ], - ], - ]; - } -} diff --git a/public/lib/classes/moodlenet/resource_packager.php b/public/lib/classes/moodlenet/resource_packager.php deleted file mode 100644 index 01dad78dc88..00000000000 --- a/public/lib/classes/moodlenet/resource_packager.php +++ /dev/null @@ -1,191 +0,0 @@ -. - -namespace core\moodlenet; - -use backup_controller; -use backup_root_task; -use cm_info; -use core\context\user; -use stdClass; -use stored_file; - -defined('MOODLE_INTERNAL') || die(); - -require_once($CFG->dirroot . '/backup/util/includes/backup_includes.php'); - -/** - * Base packager to prepare appropriate backup of a resource to share to MoodleNet. - * - * @package core - * @copyright 2023 Safat Shahin - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -abstract class resource_packager { - - /** - * @var string $resourcefilename The filename for the resource. - */ - protected string $resourcefilename = 'resource'; - - /** - * @var stdClass $course The course which the resource belongs to. - */ - protected stdClass $course; - - /** - * @var cm_info $cminfo The course module which the resource belongs to. - */ - protected cm_info $cminfo; - - /** - * @var int $userid The ID of the user performing the packaging. - */ - protected int $userid; - - /** - * Constructor for the base packager. - * - * @param stdClass|cm_info $resource The resource object - * @param int $userid The user id - */ - public function __construct( - stdClass|cm_info $resource, - int $userid, - string $resourcefilename, - ) { - if ($resource instanceof cm_info) { - $this->cminfo = $resource; - $this->course = $resource->get_course(); - } else { - $this->course = $resource; - } - - $this->userid = $userid; - $this->resourcefilename = $resourcefilename; - } - - /** - * Get the backup controller for the course. - * - * @return backup_controller The backup controller instance that will be used to package the resource. - */ - abstract protected function get_backup_controller(): backup_controller; - - /** - * Prepare the backup file using appropriate setting overrides and return relevant information. - * - * @return stored_file - */ - public function get_package(): stored_file { - $controller = $this->get_backup_controller(); - $alltasksettings = $this->get_all_task_settings($controller); - - // Override relevant settings to remove user data when packaging to share to MoodleNet. - $this->override_task_setting($alltasksettings, 'setting_root_users', 0); - $this->override_task_setting($alltasksettings, 'setting_root_role_assignments', 0); - $this->override_task_setting($alltasksettings, 'setting_root_blocks', 0); - $this->override_task_setting($alltasksettings, 'setting_root_comments', 0); - $this->override_task_setting($alltasksettings, 'setting_root_badges', 0); - $this->override_task_setting($alltasksettings, 'setting_root_userscompletion', 0); - $this->override_task_setting($alltasksettings, 'setting_root_logs', 0); - $this->override_task_setting($alltasksettings, 'setting_root_grade_histories', 0); - $this->override_task_setting($alltasksettings, 'setting_root_groups', 0); - - $storedfile = $this->package($controller); - - $controller->destroy(); // We are done with the controller, destroy it. - - return $storedfile; - } - - /** - * Get all backup settings available for override. - * - * @return array the associative array of taskclass => settings instances. - */ - protected function get_all_task_settings(backup_controller $controller): array { - $tasksettings = []; - foreach ($controller->get_plan()->get_tasks() as $task) { - $taskclass = get_class($task); - $tasksettings[$taskclass] = $task->get_settings(); - } - return $tasksettings; - } - - /** - * Override a backup task setting with a given value. - * - * @param array $alltasksettings All task settings. - * @param string $settingname The name of the setting to be overridden (task class name format). - * @param int $settingvalue Value to be given to the setting. - */ - protected function override_task_setting(array $alltasksettings, string $settingname, int $settingvalue): void { - if (empty($rootsettings = $alltasksettings[backup_root_task::class])) { - return; - } - - foreach ($rootsettings as $setting) { - $name = $setting->get_ui_name(); - if ($name == $settingname && $settingvalue != $setting->get_value()) { - $setting->set_value($settingvalue); - return; - } - } - } - - /** - * Package the resource identified by resource id into a new stored_file. - * - * @param backup_controller $controller The backup controller. - * @return stored_file - */ - protected function package(backup_controller $controller): stored_file { - // Execute the backup and fetch the result. - $controller->execute_plan(); - $result = $controller->get_results(); - - if (!isset($result['backup_destination'])) { - throw new \moodle_exception('Failed to package resource.'); - } - - $backupfile = $result['backup_destination']; - - if (!$backupfile->get_contenthash()) { - throw new \moodle_exception('Failed to package resource (invalid file).'); - } - - // Create the location we want to copy this file to. - $filerecord = [ - 'contextid' => user::instance($this->userid)->id, - 'userid' => $this->userid, - 'component' => 'user', - 'filearea' => 'draft', - 'itemid' => file_get_unused_draft_itemid(), - 'filepath' => '/', - 'filename' => $this->resourcefilename . '_backup.mbz', - ]; - - // Create the local file based on the backup. - $fs = get_file_storage(); - $file = $fs->create_file_from_storedfile($filerecord, $backupfile); - - // Delete the backup now it has been created in the file area. - $backupfile->delete(); - - return $file; - } -} diff --git a/public/lib/classes/moodlenet/resource_sender.php b/public/lib/classes/moodlenet/resource_sender.php deleted file mode 100644 index 29e4c29cf46..00000000000 --- a/public/lib/classes/moodlenet/resource_sender.php +++ /dev/null @@ -1,103 +0,0 @@ -. - -namespace core\moodlenet; - -use core\oauth2\client; -use moodle_exception; -use stdClass; -use stored_file; - -/** - * API for sharing Moodle LMS resources to MoodleNet instances. - * - * @package core - * @copyright 2023 Safat Shahin - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -abstract class resource_sender { - - /** - * @var int Backup share format - the content is being shared as a Moodle backup file. - */ - public const SHARE_FORMAT_BACKUP = 0; - - /** - * @var int Maximum upload file size (1.07 GB). - */ - public const MAX_FILESIZE = 1070000000; - - /** - * @var stdClass The course where the activity is located. - */ - protected stdClass $course; - - /** @var resource_packager Resource packager. */ - protected resource_packager $packager; - - /** - * Class constructor. - * - * @param int $resourceid The resource ID of the resource being shared. - * @param int $userid The user ID who is sharing the activity. - * @param moodlenet_client $moodlenetclient The moodlenet_client object used to perform the share. - * @param client $oauthclient The OAuth 2 client for the MoodleNet instance. - * @param int $shareformat The data format to share in. Defaults to a Moodle backup (SHARE_FORMAT_BACKUP). - * @throws moodle_exception - */ - public function __construct( - int $resourceid, - protected int $userid, - protected moodlenet_client $moodlenetclient, - protected client $oauthclient, - protected int $shareformat = self::SHARE_FORMAT_BACKUP, - ) { - if (!in_array($shareformat, self::get_allowed_share_formats(), true)) { - throw new moodle_exception('moodlenet:invalidshareformat'); - } - } - - /** - * Return the list of supported share formats. - * - * @return array Array of supported share format values. - */ - protected static function get_allowed_share_formats(): array { - return [ - self::SHARE_FORMAT_BACKUP, - ]; - } - - /** - * Share a resource to MoodleNet. - * - * @return array The HTTP response code from MoodleNet and the MoodleNet draft resource URL (URL empty string on fail). - * Format: ['responsecode' => 201, 'drafturl' => 'https://draft.mnurl/here'] - */ - abstract public function share_resource(): array; - - /** - * Prepare the data for sharing, in the format specified. - * - * @return stored_file - */ - protected function prepare_share_contents(): stored_file { - return match ($this->shareformat) { - self::SHARE_FORMAT_BACKUP => $this->packager->get_package(), - default => throw new \coding_exception("Unknown share format: {$this->shareformat}'"), - }; - } -} diff --git a/public/lib/classes/moodlenet/share_progress_table.php b/public/lib/classes/moodlenet/share_progress_table.php deleted file mode 100644 index cc46c2c99b3..00000000000 --- a/public/lib/classes/moodlenet/share_progress_table.php +++ /dev/null @@ -1,252 +0,0 @@ -. - -/** - * MoodleNet share progress table. - * - * @package core - * @copyright 2023 David Woloszyn - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -namespace core\moodlenet; - -defined('MOODLE_INTERNAL') || die(); - -require_once($CFG->libdir . '/tablelib.php'); - -use html_writer; -use moodle_url; -use stdClass; -use table_sql; - -/** - * MoodleNet share progress table. - * - * @package core - * @copyright 2023 David Woloszyn - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class share_progress_table extends table_sql { - - /** @var int The user id records will be displayed for. */ - protected $userid; - - /** - * Set up the table. - * - * @param string $uniqueid Unique id of table. - * @param moodle_url $url The base URL. - * @param int $userid The user id. - */ - public function __construct($uniqueid, $url, $userid) { - parent::__construct($uniqueid); - $this->userid = $userid; - $this->define_table_columns(); - $this->define_baseurl($url); - $this->define_table_configs(); - } - - /** - * Define table configs. - */ - protected function define_table_configs() { - $this->collapsible(false); - $this->sortable(false); - $this->pageable(true); - $this->set_default_per_page(25); - } - - /** - * Set up the columns and headers. - */ - protected function define_table_columns() { - // Define headers and columns. - $cols = [ - 'name' => get_string('name'), - 'type' => get_string('moodlenet:columntype'), - 'timecreated' => get_string('moodlenet:columnsenddate'), - 'status' => get_string('moodlenet:columnsendstatus'), - ]; - - $this->define_columns(array_keys($cols)); - $this->define_headers(array_values($cols)); - $this->column_class('status', 'text-center'); - } - - /** - * Name column. - * - * @param stdClass $row Row data. - * @return string - */ - protected function col_name(stdClass $row): string { - global $OUTPUT; - - $class = ''; - // Track deletion of resources on Moodle. - $deleted = false; - // Courses. - if ($row->type == share_recorder::TYPE_COURSE) { - if ($row->fullname) { - $name = $row->fullname; - } else { - $name = get_string('moodlenet:deletedcourse'); - $deleted = true; - } - // Activities. - } else if ($row->type == share_recorder::TYPE_ACTIVITY) { - if ($cm = get_coursemodule_from_id('', $row->cmid)) { - $name = $cm->name; - } else { - $name = get_string('moodlenet:deletedactivity'); - $deleted = true; - } - } - if ($deleted) { - $class = 'fst-italic'; - } - // Add a link to the resource if it was recorded. - if (!empty($row->resourceurl)) { - // Apply bold to resource links that aren't deleted. - if (!$deleted) { - $class = 'fw-bold'; - } - $icon = $OUTPUT->pix_icon('i/externallink', get_string('opensinnewwindow'), 'moodle', ['class' => 'ms-1']); - $text = $name . $icon; - $attributes = [ - 'target' => '_blank', - 'rel' => 'noopener noreferrer', - ]; - $name = html_writer::link($row->resourceurl, $text, $attributes); - } - - return html_writer::span($name, $class); - } - - /** - * Type column. - * - * @param stdClass $row Row data. - * @return string - */ - protected function col_type(stdClass $row): string { - // Courses. - if ($row->type == share_recorder::TYPE_COURSE) { - $type = get_string('course'); - // Activities. - } else if ($row->type == share_recorder::TYPE_ACTIVITY) { - if ($row->modname) { - $type = get_string('modulename', $row->modname); - } else { - // Alternatively, default to 'activity'. - $type = get_string('activity'); - } - } - - return $type; - } - - /** - * Time created column (Send date). - * - * @param stdClass $row Row data. - * @return string - */ - protected function col_timecreated(stdClass $row): string { - $format = get_string('strftimedatefullshort', 'core_langconfig'); - return userdate($row->timecreated, $format); - } - - /** - * Status column (Send status). - * - * @param stdClass $row Row data. - * @return string - */ - protected function col_status(stdClass $row): string { - // Display a badge indicating the status of the share. - if ($row->status == share_recorder::STATUS_IN_PROGRESS) { - $status = html_writer::span(get_string('inprogress'), 'badge bg-warning text-dark'); - } else if ($row->status == share_recorder::STATUS_SENT) { - $status = html_writer::span(get_string('sent'), 'badge bg-success text-white'); - } else if ($row->status == share_recorder::STATUS_ERROR) { - $status = html_writer::span(get_string('error'), 'badge bg-danger text-white'); - } - - return $status; - } - - /** - * Builds the SQL query. - * - * @param bool $count When true, return the count SQL. - * @return array containing sql to use and an array of params. - */ - protected function get_sql_and_params($count = false) { - if ($count) { - $select = "COUNT(1)"; - } else { - $select = "msp.id, msp.type, msp.courseid, msp.cmid, msp.timecreated, " . - "msp.resourceurl, msp.status, c.fullname, md.name AS modname"; - } - - $sql = "SELECT $select - FROM {moodlenet_share_progress} msp - LEFT JOIN {course} c ON c.id = msp.courseid - LEFT JOIN {course_modules} cm ON cm.course = msp.courseid - AND cm.id = msp.cmid - LEFT JOIN {modules} md ON md.id = cm.module - WHERE msp.userid = :userid"; - - $params = ['userid' => $this->userid]; - - if (!$count) { - $sql .= " ORDER BY msp.status DESC, msp.timecreated DESC"; - } - - return [$sql, $params]; - } - - /** - * Query the DB. - * - * @param int $pagesize size of page for paginated displayed table. - * @param bool $useinitialsbar do you want to use the initials bar. - */ - public function query_db($pagesize, $useinitialsbar = true) { - global $DB; - - list($countsql, $countparams) = $this->get_sql_and_params(true); - list($sql, $params) = $this->get_sql_and_params(); - $total = $DB->count_records_sql($countsql, $countparams); - $this->pagesize($pagesize, $total); - $this->rawdata = $DB->get_records_sql($sql, $params, $this->get_page_start(), $this->get_page_size()); - - // Set initial bars. - if ($useinitialsbar) { - $this->initialbars($total > $pagesize); - } - } - - /** - * Notification to display when there are no results. - */ - public function print_nothing_to_display() { - global $OUTPUT; - echo $OUTPUT->notification(get_string('moodlenet:nosharedresources'), 'info'); - } -} diff --git a/public/lib/classes/moodlenet/share_recorder.php b/public/lib/classes/moodlenet/share_recorder.php deleted file mode 100644 index 22d2318b663..00000000000 --- a/public/lib/classes/moodlenet/share_recorder.php +++ /dev/null @@ -1,132 +0,0 @@ -. - -namespace core\moodlenet; - -use moodle_exception; -use stdClass; - -/** - * Record the sharing of content to MoodleNet. - * - * @package core - * @copyright 2023 David Woloszyn - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class share_recorder { - - /** - * @var int The content being shared is a course. - */ - public const TYPE_COURSE = 1; - - /** - * @var int The content being shared is an activity. - */ - public const TYPE_ACTIVITY = 2; - - /** - * @var int The status of the share is 'sent'. - */ - public const STATUS_SENT = 1; - - /** - * @var int The status of the share is 'in progress'. - */ - public const STATUS_IN_PROGRESS = 2; - - /** - * @var int The status of the share is 'error'. - */ - public const STATUS_ERROR = 3; - - /** - * Get all allowed share types. - * - * @return array - */ - protected static function get_allowed_share_types(): array { - - return [ - self::TYPE_ACTIVITY, - self::TYPE_COURSE - ]; - } - - /** - * Get all allowed share statuses. - * Note that the particular status values aid in sorting. - * - * @return array - */ - protected static function get_allowed_share_statuses(): array { - - return [ - self::STATUS_SENT, - self::STATUS_IN_PROGRESS, - self::STATUS_ERROR, - ]; - } - - /** - * Create a new share progress record in the DB. - * - * @param int $sharetype The type of share (e.g. TYPE_COURSE). - * @param int $userid The ID of the user performing the share. - * @param int $courseid The associated course id. - * @param int|null $cmid The associated course module id (when sharing activity). - * @return int Returns the inserted record id. - */ - public static function insert_share_progress(int $sharetype, int $userid, int $courseid, ?int $cmid = null): int { - global $DB, $USER; - - if (!in_array($sharetype, self::get_allowed_share_types())) { - throw new moodle_exception('moodlenet:invalidsharetype'); - } - - $data = new stdClass(); - $data->type = $sharetype; - $data->courseid = $courseid; - $data->cmid = $cmid; - $data->userid = $userid; - $data->timecreated = time(); - $data->status = self::STATUS_IN_PROGRESS; - - return $DB->insert_record('moodlenet_share_progress', $data); - } - - /** - * Update the share progress record in the DB. - * - * @param int $shareid The id of the share progress row being updated. - * @param int $status The status of the share progress (e.g. STATUS_SENT). - * @param string|null $resourceurl The resource url returned from MoodleNet. - */ - public static function update_share_progress(int $shareid, int $status, ?string $resourceurl = null): void { - global $DB; - - if (!in_array($status, self::get_allowed_share_statuses())) { - throw new moodle_exception('moodlenet:invalidsharestatus'); - } - - $data = new stdClass(); - $data->id = $shareid; - $data->resourceurl = $resourceurl; - $data->status = $status; - - $DB->update_record('moodlenet_share_progress', $data); - } -} diff --git a/public/lib/classes/moodlenet/utilities.php b/public/lib/classes/moodlenet/utilities.php deleted file mode 100644 index 09098952ba8..00000000000 --- a/public/lib/classes/moodlenet/utilities.php +++ /dev/null @@ -1,123 +0,0 @@ -. - -namespace core\moodlenet; - -use core\oauth2\issuer; - -/** - * Class containing static utilities (such as various checks) required by the MoodleNet API. - * - * @package core - * @copyright 2023 Michael Hawkins - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class utilities { - /** - * Check whether the specified issuer is configured as a MoodleNet instance that can be shared to. - * - * @param issuer $issuer The OAuth 2 issuer being validated. - * @return bool true if the issuer is enabled and available to share to. - */ - public static function is_valid_instance(issuer $issuer): bool { - global $CFG; - - $issuerid = $issuer->get('id'); - $allowedissuer = get_config('moodlenet', 'oauthservice'); - - return ($CFG->enablesharingtomoodlenet && $issuerid == $allowedissuer && $issuer->get('enabled') && - $issuer->get('servicetype') == 'moodlenet'); - } - - /** - * Check whether a user has the capabilities required to share activities or courses to MoodleNet. - * - * @param \core\context\course $coursecontext Course context where the activity or course would be shared from. - * @param int $userid The user ID being checked. - * @param string $type The type of resource being checked (either 'activity' or 'course'). - * @return boolean - * @throws \coding_exception If an invalid resource type is provided. - */ - public static function can_user_share(\core\context\course $coursecontext, int $userid, string $type = 'activity'): bool { - if ($type === 'course') { - return (has_capability('moodle/moodlenet:sharecourse', $coursecontext, $userid) && - has_capability('moodle/backup:backupcourse', $coursecontext, $userid)); - } else if ($type === 'activity') { - return (has_capability('moodle/moodlenet:shareactivity', $coursecontext, $userid) && - has_capability('moodle/backup:backupactivity', $coursecontext, $userid)); - } - - throw new \coding_exception('Invalid resource type'); - } - - /** - * Get the support url. - * - * @return string - */ - public static function get_support_url(): string { - global $CFG; - $supporturl = ''; - - if ($CFG->supportavailability && $CFG->supportavailability !== CONTACT_SUPPORT_DISABLED) { - if (!empty($CFG->supportpage)) { - $supporturl = $CFG->supportpage; - } else { - $supporturl = $CFG->wwwroot . '/user/contactsitesupport.php'; - } - } - - return $supporturl; - } - - /** - * Check the user has a valid capability in any course they are enrolled in. - * - * @param int $userid The user id to query - * @return string Returns 'yes' if capability found, 'no' if not - */ - public static function does_user_have_capability_in_any_course(int $userid): string { - // We are checking this way because we are not always in the course context and need - // a way to retrieve the user's courses to see if any of them have the correct capability. - $capabilities = [ - 'moodle/moodlenet:sharecourse', - 'moodle/moodlenet:shareactivity' - ]; - // We are using 'no' instead of false to avoid confusing a cache key - // that was not found (returns false) with a user who does not have the capablity. - $isallowed = 'no'; - $cache = \cache::make('core', 'moodlenet_usercanshare'); - $cachedvalue = $cache->get($userid); - - if ($cachedvalue === false) { - foreach ($capabilities as $capability) { - // Find at least one course that contains a capability match. - $course = get_user_capability_course($capability, $userid, true, '', 'id', 1); - - if (!empty($course)) { - // Set the cache to 'yes' and break out of the loop. - $isallowed = 'yes'; - break; - } - } - $cache->set($userid, $isallowed); - } else { - $isallowed = $cachedvalue; - } - - return $isallowed; - } -} diff --git a/public/lib/classes/privacy/provider.php b/public/lib/classes/privacy/provider.php index 565bf542c5a..a888d299315 100644 --- a/public/lib/classes/privacy/provider.php +++ b/public/lib/classes/privacy/provider.php @@ -53,7 +53,7 @@ class provider implements * @return collection The collection object filled out with information about this component. */ public static function get_metadata(collection $collection): collection { - // Except for moodlenet_share_progress, these tables are really data about site configuration and not user data. + // Except for shortlink, these tables are really data about site configuration and not user data. // The config_log includes information about which user performed a configuration change. // The value and oldvalue may contain sensitive information such as accounts for service passwords.. @@ -126,22 +126,6 @@ class provider implements 'scopehash' => 'privacy:metadata:oauth2_refresh_token:scopehash' ], 'privacy:metadata:oauth2_refresh_token'); - // The moodlenet_share_progress includes details of an attempted share of a resource to MoodleNet. - $collection->add_database_table('moodlenet_share_progress', [ - 'type' => 'privacy:metadata:moodlenet_share_progress:type', - 'courseid' => 'privacy:metadata:moodlenet_share_progress:courseid', - 'cmid' => 'privacy:metadata:moodlenet_share_progress:cmid', - 'userid' => 'privacy:metadata:moodlenet_share_progress:userid', - 'timecreated' => 'privacy:metadata:moodlenet_share_progress:timecreated', - 'resourceurl' => 'privacy:metadata:moodlenet_share_progress:resourceurl', - 'status' => 'privacy:metadata:moodlenet_share_progress:status', - ], 'privacy:metadata:moodlenet_share_progress'); - - // This resourceurl field is an external link from MoodleNet. - $collection->add_external_location_link('moodlenet_share_progress', [ - 'resourceurl' => 'privacy:metadata:moodlenet_share_progress:resourceurl', - ], 'privacy:metadata:moodlenet_share_progress'); - // The shortlink table includes data that associates a user with a shortlink URL. $collection->add_database_table('shortlink', [ 'shortcode' => 'privacy:metadata:shortlink:shortcode', @@ -163,15 +147,6 @@ class provider implements public static function get_contexts_for_userid(int $userid): contextlist { $contextlist = new contextlist(); - // MoodleNet share progress uses the user context. - $sql = "SELECT ctx.id - FROM {context} ctx - JOIN {moodlenet_share_progress} msp ON ctx.instanceid = msp.userid - AND ctx.contextlevel = :contextlevel - WHERE msp.userid = :userid"; - $params = ['userid' => $userid, 'contextlevel' => CONTEXT_USER]; - $contextlist->add_from_sql($sql, $params); - // Shortlink. $sql = "SELECT ctx.id FROM {context} ctx @@ -192,16 +167,6 @@ class provider implements public static function get_users_in_context(userlist $userlist) { $context = $userlist->get_context(); - // MoodleNet share progress uses the user context. - if ($context->contextlevel == CONTEXT_USER) { - // Get all distinct userids from the table. - $sql = "SELECT DISTINCT userid - FROM {moodlenet_share_progress} - WHERE userid = :userid"; - $params = ['userid' => $context->instanceid]; - $userlist->add_from_sql('userid', $sql, $params); - } - // Shortlink. if ($context->contextlevel == CONTEXT_USER) { // Get all distinct userids from the table. @@ -219,16 +184,11 @@ class provider implements * @param approved_contextlist $contextlist The approved contexts to export information for. */ public static function export_user_data(approved_contextlist $contextlist) { - // Except for moodlenet_share_progress and shortlink, none of the core tables should be exported. + // Except for shortlink, none of the core tables should be exported. global $DB; foreach ($contextlist as $context) { if ($context->contextlevel == CONTEXT_USER && $context->instanceid == $contextlist->get_user()->id) { - // Get the user's MoodleNet share progress data. - $sharedata = $DB->get_records('moodlenet_share_progress', ['userid' => $context->instanceid]); - $subcontext = get_string('privacy:metadata:moodlenet_share_progress', 'moodle'); - writer::with_context($context)->export_data([$subcontext], (object) $sharedata); - // Get the user's shortlink data. $shortlinkdata = $DB->get_records('shortlink', ['userid' => $context->instanceid]); $subcontext = get_string('privacy:metadata:shortlink', 'moodle'); @@ -243,14 +203,9 @@ class provider implements * @param \context $context The specific context to delete data for. */ public static function delete_data_for_all_users_in_context(\context $context) { - // Except for moodlenet_share_progress and shortlink, none of the data from these tables should be deleted. + // Except for shortlink, none of the data from these tables should be deleted. global $DB; - // MoodleNet share progress uses the user context. - if ($context->contextlevel == CONTEXT_USER) { - $DB->delete_records('moodlenet_share_progress', ['userid' => $context->instanceid]); - } - // Shortlink. if ($context->contextlevel == CONTEXT_USER) { $DB->delete_records('shortlink', ['userid' => $context->instanceid]); @@ -263,15 +218,13 @@ class provider implements * @param approved_contextlist $contextlist The approved contexts and user information to delete information for. */ public static function delete_data_for_user(approved_contextlist $contextlist) { - // Except for moodlenet_share_progress and shortlink, none of the data from these tables should be deleted. + // Except for shortlink, none of the data from these tables should be deleted. // Note: Although it may be tempting to delete the adhoc task data, do not do so. // The delete process is run as an adhoc task. global $DB; foreach ($contextlist as $context) { if ($context->contextlevel == CONTEXT_USER && $context->instanceid == $contextlist->get_user()->id) { - // MoodleNet share progress uses the user context. - $DB->delete_records('moodlenet_share_progress', ['userid' => $context->instanceid]); // Shortlink. $DB->delete_records('shortlink', ['userid' => $context->instanceid]); } @@ -284,7 +237,7 @@ class provider implements * @param approved_userlist $userlist The approved context and user information to delete information for. */ public static function delete_data_for_users(approved_userlist $userlist) { - // Except for moodlenet_share_progress and shortlink, none of the data from these tables should be deleted. + // Except for shortlink, none of the data from these tables should be deleted. // Note: Although it may be tempting to delete the adhoc task data, do not do so. // The delete process is run as an adhoc task. global $DB; @@ -296,8 +249,6 @@ class provider implements } if ($context->contextlevel == CONTEXT_USER) { - // MoodleNet share progress uses the user context. - $DB->delete_records('moodlenet_share_progress', ['userid' => $context->instanceid]); // Shortlink. $DB->delete_records('shortlink', ['userid' => $context->instanceid]); } diff --git a/public/lib/db/access.php b/public/lib/db/access.php index 9c0c402ac2c..53e99f65af1 100644 --- a/public/lib/db/access.php +++ b/public/lib/db/access.php @@ -2767,16 +2767,6 @@ $capabilities = array( 'archetypes' => [], ], - // Allow users to share activities to MoodleNet. - 'moodle/moodlenet:shareactivity' => [ - 'captype' => 'read', - 'contextlevel' => CONTEXT_COURSE, - 'archetypes' => [ - 'editingteacher' => CAP_ALLOW, - 'manager' => CAP_ALLOW, - ] - ], - // Allow users to configure course communication rooms. 'moodle/course:configurecoursecommunication' => [ 'captype' => 'write', @@ -2787,16 +2777,6 @@ $capabilities = array( ] ], - // Allow users to share courses to MoodleNet. - 'moodle/moodlenet:sharecourse' => [ - 'captype' => 'read', - 'contextlevel' => CONTEXT_COURSE, - 'archetypes' => [ - 'editingteacher' => CAP_ALLOW, - 'manager' => CAP_ALLOW, - ] - ], - // Allow users to edit course welcome messages. 'moodle/course:editcoursewelcomemessage' => [ 'captype' => 'write', diff --git a/public/lib/db/caches.php b/public/lib/db/caches.php index 376e979fe51..50193fe03d9 100644 --- a/public/lib/db/caches.php +++ b/public/lib/db/caches.php @@ -592,19 +592,6 @@ $definitions = array( 'staticaccelerationsize' => 100, ], - // Cache if a user has the capability to share to MoodleNet. - 'moodlenet_usercanshare' => [ - 'mode' => cache_store::MODE_SESSION, - 'simplekeys' => true, - 'simpledata' => true, - 'ttl' => 1800, - 'invalidationevents' => [ - 'changesincoursecat', - 'changesincategoryenrolment', - 'changesincourse', - ], - ], - // A theme has been used in context to override the default theme. // Applies to user, cohort, category and course. 'theme_usedincontext' => [ diff --git a/public/lib/db/install.xml b/public/lib/db/install.xml index 209ea8115c6..6a0fff36a18 100644 --- a/public/lib/db/install.xml +++ b/public/lib/db/install.xml @@ -4884,21 +4884,6 @@ - - - - - - - - - - - - - - -
diff --git a/public/lib/db/services.php b/public/lib/db/services.php index 174a6838742..9876330cb66 100644 --- a/public/lib/db/services.php +++ b/public/lib/db/services.php @@ -3247,36 +3247,6 @@ $functions = array( 'type' => 'write', 'ajax' => true, ], - 'core_moodlenet_send_activity' => [ - 'classname' => 'core\external\moodlenet_send_activity', - 'description' => 'Send activity to MoodleNet', - 'type' => 'read', - 'ajax' => true, - ], - 'core_moodlenet_get_share_info_activity' => [ - 'classname' => 'core\external\moodlenet_get_share_info_activity', - 'description' => 'Get information about an activity being shared', - 'type' => 'read', - 'ajax' => true, - ], - 'core_moodlenet_auth_check' => [ - 'classname' => 'core\external\moodlenet_auth_check', - 'description' => 'Check a user has authorized for a given MoodleNet site', - 'type' => 'write', - 'ajax' => true, - ], - 'core_moodlenet_get_shared_course_info' => [ - 'classname' => 'core\external\moodlenet_get_shared_course_info', - 'description' => 'Get information about an course being shared', - 'type' => 'read', - 'ajax' => true, - ], - 'core_moodlenet_send_course' => [ - 'classname' => 'core\external\moodlenet_send_course', - 'description' => 'Send course to MoodleNet', - 'type' => 'read', - 'ajax' => true, - ], 'core_output_poll_stored_progress' => [ 'classname' => 'core\external\output\poll_stored_progress', 'methodname' => 'execute', diff --git a/public/lib/db/upgrade.php b/public/lib/db/upgrade.php index 8f52abed21e..95b1c83b5de 100644 --- a/public/lib/db/upgrade.php +++ b/public/lib/db/upgrade.php @@ -1043,7 +1043,7 @@ function xmldb_main_upgrade($oldversion) { // Handle custom params. if (isset($action['settings']['modelextraparams'])) { $modelsettings['custom']['modelextraparams'] = $action['settings']['modelextraparams'] ?? ''; - // Handle known models and their keys. + // Handle known models and their keys. } else if (isset($affectedkeys[$model])) { foreach ($affectedkeys[$model] as $key) { $modelsettings[$model][$key] = $action['settings'][$key] ?? ''; @@ -1445,7 +1445,7 @@ function xmldb_main_upgrade($oldversion) { $dbman->add_field($table, $field); } - // Define field area to be added to customfield_data. + // Define field area to be added to customfield_data. $table = new xmldb_table('customfield_data'); $field = new xmldb_field('area', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null, 'component'); @@ -1621,7 +1621,7 @@ function xmldb_main_upgrade($oldversion) { } if ($oldversion < 2025121900.01) { - // Define field nextversion to be added to question_bank_entries. + // Define field nextversion to be added to question_bank_entries. $table = new xmldb_table('question_bank_entries'); $field = new xmldb_field('nextversion', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'ownerid'); @@ -1760,5 +1760,33 @@ function xmldb_main_upgrade($oldversion) { upgrade_main_savepoint(true, 2026022700.02); } + if ($oldversion < 2026030600.01) { + // Remove MoodleNet outbound sharing functionality. + + // Drop the moodlenet_share_progress table if it exists. + $table = new xmldb_table('moodlenet_share_progress'); + if ($dbman->table_exists($table)) { + $dbman->drop_table($table); + } + + // Remove the enablesharingtomoodlenet config setting. + unset_config('enablesharingtomoodlenet'); + + // Remove MoodleNet outbound OAuth2 configuration. + unset_config('oauthservice', 'moodlenet'); + $issuerids = $DB->get_fieldset_select('oauth2_issuer', 'id', "servicetype = ?", ['moodlenet']); + if (!empty($issuerids)) { + $DB->delete_records_list('oauth2_endpoint', 'issuerid', $issuerids); + $DB->delete_records_list('oauth2_access_token', 'issuerid', $issuerids); + $DB->delete_records_list('oauth2_refresh_token', 'issuerid', $issuerids); + $DB->delete_records_list('oauth2_system_account', 'issuerid', $issuerids); + $DB->delete_records_list('oauth2_user_field_mapping', 'issuerid', $issuerids); + $DB->delete_records_list('oauth2_issuer', 'id', $issuerids); + } + + // Main savepoint reached. + upgrade_main_savepoint(true, 2026030600.01); + } + return true; } diff --git a/public/lib/templates/moodlenet/send_activity_modal_base.mustache b/public/lib/templates/moodlenet/send_activity_modal_base.mustache deleted file mode 100644 index ff2521e5660..00000000000 --- a/public/lib/templates/moodlenet/send_activity_modal_base.mustache +++ /dev/null @@ -1,60 +0,0 @@ -{{! - This file is part of Moodle - http://moodle.org/ - Moodle is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - Moodle is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with Moodle. If not, see . -}} -{{! - @template core/moodlenet/send_activity_modal_base - Modal to send activity to MoodleNet - Example context (json): - { - "uniqid": 123456, - "activitytype": "assignment", - "activityname": "Test assignment", - "sharetype": "resource" - } -}} - diff --git a/public/lib/templates/moodlenet/send_activity_modal_done.mustache b/public/lib/templates/moodlenet/send_activity_modal_done.mustache deleted file mode 100644 index 4d13ce686cb..00000000000 --- a/public/lib/templates/moodlenet/send_activity_modal_done.mustache +++ /dev/null @@ -1,57 +0,0 @@ -{{! - This file is part of Moodle - http://moodle.org/ - Moodle is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - Moodle is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with Moodle. If not, see . -}} -{{! - @template core/moodlenet/send_activity_modal_done - This template renders done state for share modal. - Example context (json): - { - "success": true, - "sitesupporturl": "https://moodle.test/contactsitesupport.php" - } -}} -
-
- - {{#success}} - {{#pix}} t/check, core {{/pix}} - {{/success}} - {{^success}} - {{#pix}} fp/cross, theme {{/pix}} - {{/success}} - - - {{#success}} - {{#str}} moodlenet:sharesuccesstitle, moodle {{/str}} - {{/success}} - {{^success}} - {{#str}} moodlenet:sharefailtitle, moodle {{/str}} - {{/success}} - -
-
- - {{#success}} - {{#str}} moodlenet:sharesuccesstext, moodle {{/str}} - {{/success}} - {{^success}} - {{#sitesupporturl}} - {{#str}} moodlenet:sharefailtextwithsitesupport, moodle, {{sitesupporturl}} {{/str}} - {{/sitesupporturl}} - {{^sitesupporturl}} - {{#str}} moodlenet:sharefailtext, moodle {{/str}} - {{/sitesupporturl}} - {{/success}} - -
-
diff --git a/public/lib/templates/moodlenet/send_activity_modal_footer_share.mustache b/public/lib/templates/moodlenet/send_activity_modal_footer_share.mustache deleted file mode 100644 index df065ac03d6..00000000000 --- a/public/lib/templates/moodlenet/send_activity_modal_footer_share.mustache +++ /dev/null @@ -1,28 +0,0 @@ -{{! - This file is part of Moodle - http://moodle.org/ - Moodle is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - Moodle is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with Moodle. If not, see . -}} -{{! - @template core/moodlenet/send_activity_modal_footer_share - Render the footer for sharing activity - Example context (json): - { - "server": "MoodleNet Local" - } -}} -
- {{#str}} moodlenet:sharingto, moodle {{/str}}{{server}} -
-
- - -
diff --git a/public/lib/templates/moodlenet/send_activity_modal_footer_view.mustache b/public/lib/templates/moodlenet/send_activity_modal_footer_view.mustache deleted file mode 100644 index 93ca6b33ab4..00000000000 --- a/public/lib/templates/moodlenet/send_activity_modal_footer_view.mustache +++ /dev/null @@ -1,26 +0,0 @@ -{{! - This file is part of Moodle - http://moodle.org/ - Moodle is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - Moodle is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with Moodle. If not, see . -}} -{{! - @template core/moodlenet/send_activity_modal_footer_view - Render the footer for sharing activity - Example context (json): - { - "resourceurl": "https://moodlenet.test/draft/activity.mbz" - } -}} - diff --git a/public/lib/templates/moodlenet/send_activity_modal_packaging.mustache b/public/lib/templates/moodlenet/send_activity_modal_packaging.mustache deleted file mode 100644 index 7de46341eb0..00000000000 --- a/public/lib/templates/moodlenet/send_activity_modal_packaging.mustache +++ /dev/null @@ -1,28 +0,0 @@ -{{! - This file is part of Moodle - http://moodle.org/ - Moodle is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - Moodle is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with Moodle. If not, see . -}} -{{! - @template core/moodlenet/send_activity_modal_packaging - This template renders the packaging stage for MoodleNet. - Example context (json): - { - } -}} -
-
{{#str}} moodlenet:sharingstatus, moodle {{/str}}
-
{{#str}} moodlenet:sharinglargefile, moodle {{/str}}
-
- {{> core/loading }} -
-
{{#str}} moodlenet:packagingandsending, moodle {{/str}}
-
diff --git a/public/moodlenet/shareprogress.php b/public/moodlenet/shareprogress.php deleted file mode 100644 index d7653a2900b..00000000000 --- a/public/moodlenet/shareprogress.php +++ /dev/null @@ -1,56 +0,0 @@ -. - -/** - * View the progress of MoodleNet shares. - * - * @package core - * @copyright 2023 David Woloszyn - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -use core\moodlenet\utilities; - -require_once('../config.php'); - -require_login(); -if (isguestuser()) { - throw new \moodle_exception('noguest'); -} - -// Capability was not found. -if (utilities::does_user_have_capability_in_any_course($USER->id) === 'no') { - throw new \moodle_exception('nocapabilitytousethisservice'); -} - -$pageurl = $CFG->wwwroot . '/moodlenet/shareprogress.php'; -$PAGE->set_url($pageurl); -$PAGE->set_context(context_system::instance()); -$PAGE->set_title(get_string('moodlenet:shareprogress')); -$PAGE->set_heading(get_string('moodlenet:shareprogress')); -$PAGE->set_pagelayout('standard'); - -echo $OUTPUT->header(); - -// Intro paragraph. -echo html_writer::div(get_string('moodlenet:shareprogressinfo'), 'mb-4'); - -// Build table. -$table = new core\moodlenet\share_progress_table('moodlenet-share-progress', $pageurl, $USER->id); -$perpage = $table->get_default_per_page(); -$table->out($perpage, true); - -echo $OUTPUT->footer(); diff --git a/public/version.php b/public/version.php index 0455db2a43f..64f8c99444e 100644 --- a/public/version.php +++ b/public/version.php @@ -29,7 +29,7 @@ defined('MOODLE_INTERNAL') || die(); -$version = 2026030600.00; // YYYYMMDD = weekly release date of this DEV branch. +$version = 2026030600.01; // YYYYMMDD = weekly release date of this DEV branch. // RR = release increments - 00 in DEV branches. // .XX = incremental changes. $release = '5.2dev (Build: 20260306)'; // Human-friendly version name