diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
new file mode 100644
index 0000000..866a43f
--- /dev/null
+++ b/.github/pull_request_template.md
@@ -0,0 +1,9 @@
+## Description
+
+
+## Testing
+
+
+
+## Jira Link
+
\ No newline at end of file
diff --git a/.github/workflows/moodle-plugin-ci.yml b/.github/workflows/moodle-plugin-ci.yml
index b736c7f..fb77a72 100644
--- a/.github/workflows/moodle-plugin-ci.yml
+++ b/.github/workflows/moodle-plugin-ci.yml
@@ -38,17 +38,17 @@ jobs:
fail-fast: false
matrix:
include:
- - php: '8.0'
+ - php: '8.1'
moodle-branch: 'master'
database: 'pgsql'
- - php: '8.0'
- moodle-branch: 'MOODLE_400_STABLE'
+ - php: '8.2'
+ moodle-branch: 'MOODLE_403_STABLE'
database: 'mariadb'
- - php: '7.4'
- moodle-branch: 'MOODLE_311_STABLE'
+ - php: '8.1'
+ moodle-branch: 'MOODLE_402_STABLE'
database: 'pgsql'
- - php: '7.4'
- moodle-branch: 'MOODLE_39_STABLE'
+ - php: '8.1'
+ moodle-branch: 'MOODLE_401_STABLE'
database: 'mariadb'
steps:
diff --git a/Gruntfile.js b/Gruntfile.js
index 562fad1..216c747 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -1,152 +1,41 @@
-// 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 .
-/* jshint node: true, browser: false */
-/* eslint-env node */
-
-/**
- * @copyright 2021 Panopto
- * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-
-/**
- * Grunt configuration
- */
-
-/* eslint-env node */
-module.exports = function(grunt) {
- var path = require('path'),
- tasks = {},
- cwd = process.env.PWD || process.cwd(),
- async = require('async');
-
- // Windows users can't run grunt in a subdirectory, so allow them to set
- // the root by passing --root=path/to/dir.
- if (grunt.option('root')) {
- var root = grunt.option('root');
- if (grunt.file.exists(__dirname, root)) {
- cwd = path.join(__dirname, root);
- grunt.log.ok('Setting root to ' + cwd);
- } else {
- grunt.fail.fatal('Setting root to ' + root + ' failed - path does not exist');
- }
- }
-
- var files = null;
- if (grunt.option('files')) {
- // Accept a comma separated list of files to process.
- files = grunt.option('files').split(',');
- }
-
+module.exports = function (grunt) {
// Project configuration.
grunt.initConfig({
- shifter: {
- options: {
- recursive: true,
- paths: files ? files : [cwd]
- }
- }
+ pkg: grunt.file.readJSON("package.json"),
+
+ // Configuration for uglify task to minify JS files.
+ uglify: {
+ build: {
+ files: [
+ {
+ expand: true,
+ cwd: "amd/src",
+ src: "*.js",
+ dest: "amd/build",
+ ext: ".min.js",
+ },
+ ],
+ },
+ },
+
+ // Configuration for watch task to monitor changes in JS files.
+ watch: {
+ scripts: {
+ files: ["amd/src/**/*.js"],
+ tasks: ["uglify"],
+ options: {
+ spawn: false,
+ },
+ },
+ },
});
- /**
- * Shifter task. Is configured with a path to a specific file or a directory,
- * in the case of a specific file it will work out the right module to be built.
- *
- * Note that this task runs the invidiaul shifter jobs async (becase it spawns
- * so be careful to to call done().
- */
- tasks.shifter = function() {
- var done = this.async(),
- options = grunt.config('shifter.options');
-
- // Run the shifter processes one at a time to avoid confusing output.
- async.eachSeries(options.paths, function(src, filedone) {
- var args = [];
- args.push(path.normalize(__dirname + '/node_modules/shifter/bin/shifter'));
-
- // Always ignore the node_modules directory.
- args.push('--excludes', 'node_modules');
-
- // Determine the most appropriate options to run with based upon the current location.
- if (grunt.file.isMatch('**/yui/**/*.js', src)) {
- // When passed a JS file, build our containing module (this happen with
- // watch).
- grunt.log.debug('Shifter passed a specific JS file');
- src = path.dirname(path.dirname(src));
- options.recursive = false;
- } else if (grunt.file.isMatch('**/yui/src', src)) {
- // When in a src directory --walk all modules.
- grunt.log.debug('In a src directory');
- args.push('--walk');
- options.recursive = false;
- } else if (grunt.file.isMatch('**/yui/src/*', src)) {
- // When in module, only build our module.
- grunt.log.debug('In a module directory');
- options.recursive = false;
- } else if (grunt.file.isMatch('**/yui/src/*/js', src)) {
- // When in module src, only build our module.
- grunt.log.debug('In a source directory');
- src = path.dirname(src);
- options.recursive = false;
- }
-
- // Add the stderr option if appropriate
- if (grunt.option('verbose')) {
- args.push('--lint-stderr');
- }
-
- if (grunt.option('no-color')) {
- args.push('--color=false');
- }
-
- var execShifter = function() {
-
- grunt.log.ok("Running shifter on " + src);
- grunt.util.spawn({
- cmd: "node",
- args: args,
- opts: {cwd: src, stdio: 'inherit', env: process.env}
- }, function(error, result, code) {
- if (code) {
- grunt.fail.fatal('Shifter failed with code: ' + code);
- } else {
- grunt.log.ok('Shifter build complete.');
- filedone();
- }
- });
- };
-
- // Actually run shifter.
- if (!options.recursive) {
- execShifter();
- } else {
- // Check that there are yui modules otherwise shifter ends with exit code 1.
- if (grunt.file.expand({cwd: src}, '**/yui/src/**/*.js').length > 0) {
- args.push('--recursive');
- execShifter();
- } else {
- grunt.log.ok('No YUI modules to build.');
- filedone();
- }
- }
- }, done);
- };
-
- // Register JS tasks.
- grunt.registerTask('shifter', 'Run Shifter against the current directory', tasks.shifter);
+ // Load the plugin that provides the "uglify" task.
+ grunt.loadNpmTasks("grunt-contrib-uglify");
+ // Load the plugin that provides the "watch" task.
+ grunt.loadNpmTasks("grunt-contrib-watch");
- // Register the default task.
- grunt.registerTask('default', ['shifter']);
+ // Default task(s).
+ grunt.registerTask("default", ["uglify", "watch"]);
};
diff --git a/README.md b/README.md
index 03ad426..92e01f0 100644
--- a/README.md
+++ b/README.md
@@ -6,27 +6,39 @@ For the most up to date documentation for the Panopto Student Submission plugin
## Installation
-1. Download the Moodle Panopto Student Submission zip file from the [github repository](https://github.com/Panopto/Moodle-Panopto-Student-Submission/releases). We will work with Moodle.org to add this into the app directory. Until then please use our github as the official release site.
+1. Download the Moodle Panopto Student Submission zip file from the [github repository](https://github.com/Panopto/Moodle-Panopto-Student-Submission/releases). You can also download this plugin from the [official moodle.org page](https://moodle.org/plugins/mod_panoptosubmission).
2. Navigate to the target Moodle site and log in as an administrator
-3. Navigate to Site Administration -> Plugins -> Install Plugins
+3. Navigate to ```Site Administration -> Plugins -> Install Plugins```
4. Drag the zip file into the drag & drop box and go through the installation process.
-5. An LTI Tool for the Panopto server must be configured on the Moodle site. If one does not already exist for your Panopto site please navigate to Site administration -> Plugins -> Activity modules -> External tool -> Manage preconfigured tools
-6. Click Add Preconfigured tool.
+5. An LTI Tool for the Panopto server must be configured on the Moodle site. If one does not already exist for your Panopto site please navigate to ```Site Administration -> Plugins -> Activity modules -> External tool -> Manage preconfigured tools```
+6. Click ```Add Preconfigured tool```
7. Input the following information
- - Tool Name: [panoptoServer] Student Submission Tool
- - Tool Url: https://[panoptoServer]/Panopto/LTI/LTI.aspx
- - Consumer Key:[Identity Provider instance name]
- - Shared secret: [Identity Provided application key]
- - Custom Parameters:
- ```
- panopto_student_submission_tool=true
- panopto_single_selection=true
- panopto_assignment_submission_content_item=true
- use_panopto_sandbox=true
- - This custom parameter will give students personal folders regardless of IdP setting.
- ```
+
+ - For LTI 1.1:
+ - Tool Name: ```[panoptoServer] Course Embed Tool```
+ - Tool Url: ```https://[panoptoServer]/Panopto/LTI/LTI.aspx```
+ - Consumer Key: ```[Identity Provider > Instance Name]```
+ - Shared secret: ```[Identity Provided > Application Key]```
+ - Custom Parameters:
+ ```
+ panopto_student_submission_tool=true
+ panopto_single_selection=true
+ panopto_assignment_submission_content_item=true
+ use_panopto_sandbox=true
+ - This custom parameter will give students personal folders regardless of IdP setting.
+ ```
+ - For LTI 1.3:
+ - Tool Name: ```[panoptoServer] Course Embed Tool```
+ - Url: ```https://[panoptoServer]/Panopto/LTI/LTI.aspx```
+ - LTI version: ```LTI 1.3```
+ - Client ID: ```[Identity Provider > LTI 1.3 Client Identifier]```
+ - Public key type: ```Keyset URL```
+ - Public keyset: ```[Identity Provider > LTI 1.3 Tool JWKS URL]```
+ - Initiate login URL: ```[Identity Provider > LTI 1.3 Tool Login URL]```
+ - Redirection URI(s): ```[Identity Provider > LTI 1.3 Tool Redirection URL]```
+
8. Save the LTI Tool
## Pre-Requisites
-- The [Panopto block for Moodle](https://github.com/Panopto/Moodle-2.0-plugin-for-Panopto) is installed on the Moodle site.
-- The target course must be provisioned with Panopto.
+- The [Panopto block for Moodle](https://github.com/Panopto/Moodle-2.0-plugin-for-Panopto) is installed on the Moodle site with at least version 2022122000.
+- The target course must be provisioned with Panopto.
\ No newline at end of file
diff --git a/amd/build/submissionpanel.min.js b/amd/build/submissionpanel.min.js
new file mode 100644
index 0000000..c3254b5
--- /dev/null
+++ b/amd/build/submissionpanel.min.js
@@ -0,0 +1 @@
+define(["jquery","core/notification","core/modal_factory","core/str"],(l,r,i,m)=>{let u=null;var e=(t,e,a)=>{Promise.all([m.get_string("select_submission","panoptosubmission"),i.create({type:i.types.DEFAULT,body:``})]).then(([t,i])=>{i.setTitle(t),i.getRoot().addClass("mod-panoptosubmission-modal-custom-size"),i.getRoot().find(".modal-dialog").addClass("mod-panoptosubmission-modal-dialog-custom").css({width:a+"px","max-width":a+"px"}),i.getRoot().find(".modal-content").addClass("mod-panoptosubmission-modal-content-custom").css({height:e+"px","max-height":e+"px"}),i.getRoot().find(".modal-body").addClass("mod-panoptosubmission-modal-body-custom"),i.show(),document.body.panoptoWindow=i,document.body.addEventListener("sessionSelected",d.bind(this),!1)}).catch(r.exception)},d=t=>{l("input[id=submit_video]").removeAttr("disabled");var i=l("iframe[id=contentframe]"),e=l("div[id=contentcontainer]"),a=l("img[id=panoptothumbnail]"),d=l("a[id=panoptothumbnaillink]"),o=l("a[id=panoptosessiontitle]"),s=new URL(t.detail.ltiViewerUrl),n=s.searchParams;n.set("course",u),n.set("custom",decodeURI(t.detail.customData)),n.set("contentUrl",t.detail.contentUrl),s.search=n.toString(),l("input[id=sessiontitle]").attr("value",t.detail.title),l("input[id=source]").attr("value",t.detail.contentUrl),l("input[id=customdata]").attr("value",t.detail.customData),l("input[id=width]").attr("value",t.detail.width),l("input[id=height]").attr("value",t.detail.height),l("input[id=thumbnailsource]").attr("value",t.detail.thumbnailUrl),l("input[id=thumbnailwidth]").attr("value",t.detail.thumbnailWidth),l("input[id=thumbnailheight]").attr("value",t.detail.thumbnailHeight),o.text(t.detail.title),o.attr("href",s.toString()),d.attr("href",s.toString()),a.attr("src",t.detail.thumbnailUrl),a.attr("width",t.detail.thumbnailWidth),a.attr("height",t.detail.thumbnailHeight),i.attr("width",t.detail.width),i.attr("height",t.detail.height),i.hasClass("session-hidden")||i.attr("src",s.toString()),e.removeClass("no-session"),m.get_string("replacevideo","panoptosubmission").done(t=>{l("#id_add_video").val(t)}).fail(r.exception),l("#id_add_video").addClass("btn-secondary"),l("#submit_video").addClass("btn-primary"),l("#id_add_video").removeClass("btn-primary"),l("#submit_video").removeClass("btn-secondary"),document.body.panoptoWindow.destroy()};return{initsubmissionpanel:t=>{"0"!==t.addvidbtnid&&"0"!==t.ltilaunchurl&&0!==t.courseid&&0!==t.height&&0!==t.width&&(u=t.courseid,l("#"+t.addvidbtnid).on("click",()=>{e(t.ltilaunchurl,t.height,t.width)}))}}});
\ No newline at end of file
diff --git a/amd/src/submissionpanel.js b/amd/src/submissionpanel.js
new file mode 100644
index 0000000..55f673a
--- /dev/null
+++ b/amd/src/submissionpanel.js
@@ -0,0 +1,184 @@
+// 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 .
+
+/**
+ * AMD module for displaying an LTI launch within a AMD panel.
+ *
+ * @package mod_panoptosubmission
+ * @copyright Panopto 2024
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+define([
+ "jquery",
+ "core/notification",
+ "core/modal_factory",
+ "core/str",
+], ($, notification, ModalFactory, str) =>
+{
+ let courseId = null;
+
+ var init = (params) =>
+ {
+ if ( "0" === params.addvidbtnid
+ || "0" === params.ltilaunchurl
+ || 0 === params.courseid
+ || 0 === params.height
+ || 0 === params.width)
+ {
+ return;
+ }
+
+ courseId = params.courseid;
+
+ let addVideoBtn = $("#" + params.addvidbtnid);
+ addVideoBtn.on("click", () =>
+ {
+ open_panopto_window_callback(
+ params.ltilaunchurl,
+ params.height,
+ params.width
+ );
+ });
+ };
+
+ var open_panopto_window_callback = (url, height, width) =>
+ {
+ // Modal custom size class.
+ let modalClass = "mod-panoptosubmission-modal-custom-size";
+
+ // Ensure unique class names for dynamic styling.
+ let modalDialogClass = "mod-panoptosubmission-modal-dialog-custom";
+ let modalContentClass = "mod-panoptosubmission-modal-content-custom";
+ let modalBodyClass = "mod-panoptosubmission-modal-body-custom";
+ let iframeClass = "mod-panoptosubmission-iframe-custom";
+
+ Promise.all([
+ str.get_string("select_submission", "panoptosubmission"),
+ ModalFactory.create({
+ type: ModalFactory.types.DEFAULT,
+ body: ``,
+ }),
+ ])
+ .then(([selectText, modal]) =>
+ {
+ modal.setTitle(selectText);
+ modal.getRoot().addClass(modalClass);
+ modal
+ .getRoot()
+ .find(".modal-dialog")
+ .addClass(modalDialogClass)
+ .css({
+ width: `${width}px`,
+ "max-width": `${width}px`,
+ });
+ modal
+ .getRoot()
+ .find(".modal-content")
+ .addClass(modalContentClass)
+ .css({
+ height: `${height}px`,
+ "max-height": `${height}px`,
+ });
+ modal
+ .getRoot()
+ .find(".modal-body")
+ .addClass(modalBodyClass);
+ modal.show();
+
+ document.body.panoptoWindow = modal;
+ document.body.addEventListener(
+ "sessionSelected",
+ close_popup_callback.bind(this),
+ false
+ );
+ }).catch(notification.exception);
+ };
+
+ var close_popup_callback = (closeEvent) =>
+ {
+ $("input[id=submit_video]").removeAttr("disabled");
+
+ let iFrameNode = $("iframe[id=contentframe]"),
+ contentWrapperNode = $("div[id=contentcontainer]"),
+ thumbnailNode = $("img[id=panoptothumbnail]"),
+ thumbnailLinkNode = $("a[id=panoptothumbnaillink]"),
+ titleNode = $("a[id=panoptosessiontitle]"),
+ newSubmissionSource = new URL(closeEvent.detail.ltiViewerUrl),
+ searchParams = newSubmissionSource.searchParams;
+
+ searchParams.set("course", courseId);
+ searchParams.set("custom", decodeURI(closeEvent.detail.customData));
+ searchParams.set("contentUrl", closeEvent.detail.contentUrl);
+
+ newSubmissionSource.search = searchParams.toString();
+
+ $("input[id=sessiontitle]").attr("value", closeEvent.detail.title);
+ $("input[id=source]").attr("value", closeEvent.detail.contentUrl);
+ $("input[id=customdata]").attr(
+ "value",
+ closeEvent.detail.customData
+ );
+ $("input[id=width]").attr("value", closeEvent.detail.width);
+ $("input[id=height]").attr("value", closeEvent.detail.height);
+ $("input[id=thumbnailsource]").attr(
+ "value",
+ closeEvent.detail.thumbnailUrl
+ );
+ $("input[id=thumbnailwidth]").attr(
+ "value",
+ closeEvent.detail.thumbnailWidth
+ );
+ $("input[id=thumbnailheight]").attr(
+ "value",
+ closeEvent.detail.thumbnailHeight
+ );
+
+ titleNode.text(closeEvent.detail.title);
+ titleNode.attr("href", newSubmissionSource.toString());
+
+ thumbnailLinkNode.attr("href", newSubmissionSource.toString());
+ thumbnailNode.attr("src", closeEvent.detail.thumbnailUrl);
+ thumbnailNode.attr("width", closeEvent.detail.thumbnailWidth);
+ thumbnailNode.attr("height", closeEvent.detail.thumbnailHeight);
+
+ iFrameNode.attr("width", closeEvent.detail.width);
+ iFrameNode.attr("height", closeEvent.detail.height);
+
+ if (!iFrameNode.hasClass("session-hidden"))
+ {
+ iFrameNode.attr("src", newSubmissionSource.toString());
+ }
+
+ contentWrapperNode.removeClass("no-session");
+
+ str.get_string("replacevideo", "panoptosubmission")
+ .done((replaceText) =>
+ {
+ $("#id_add_video").val(replaceText);
+ })
+ .fail(notification.exception);
+
+ $("#id_add_video").addClass("btn-secondary");
+ $("#submit_video").addClass("btn-primary");
+ $("#id_add_video").removeClass("btn-primary");
+ $("#submit_video").removeClass("btn-secondary");
+ document.body.panoptoWindow.destroy();
+ };
+
+ return {
+ initsubmissionpanel: init,
+ };
+});
diff --git a/backup/moodle2/backup_panoptosubmission_stepslib.php b/backup/moodle2/backup_panoptosubmission_stepslib.php
index e8e3247..11e3a56 100644
--- a/backup/moodle2/backup_panoptosubmission_stepslib.php
+++ b/backup/moodle2/backup_panoptosubmission_stepslib.php
@@ -40,7 +40,7 @@ protected function define_structure() {
$userinfo = $this->get_setting_value('userinfo');
// Define each element separated.
- $columns = array(
+ $columns = [
'course',
'name',
'intro',
@@ -55,13 +55,13 @@ protected function define_structure() {
'sendstudentnotifications',
'grade',
'timecreated',
- 'timemodified'
- );
- $panoptosubmission = new backup_nested_element('panoptosubmission', array('id'), $columns);
+ 'timemodified',
+ ];
+ $panoptosubmission = new backup_nested_element('panoptosubmission', ['id'], $columns);
$issues = new backup_nested_element('submissions');
- $columns = array(
+ $columns = [
'userid',
'entry_id',
'source',
@@ -77,16 +77,16 @@ protected function define_structure() {
'mailed',
'timemarked',
'timecreated',
- 'timemodified'
- );
- $issue = new backup_nested_element('submission', array('id'), $columns);
+ 'timemodified',
+ ];
+ $issue = new backup_nested_element('submission', ['id'], $columns);
$panoptosubmission->add_child($issues);
$issues->add_child($issue);
- $panoptosubmission->set_source_table('panoptosubmission', array('id' => backup::VAR_ACTIVITYID));
+ $panoptosubmission->set_source_table('panoptosubmission', ['id' => backup::VAR_ACTIVITYID]);
if ($userinfo) {
- $issue->set_source_table('panoptosubmission_submission', array('panactivityid' => backup::VAR_PARENTID));
+ $issue->set_source_table('panoptosubmission_submission', ['panactivityid' => backup::VAR_PARENTID]);
}
$issue->annotate_ids('user', 'userid');
diff --git a/backup/moodle2/restore_panoptosubmission_activity_task.class.php b/backup/moodle2/restore_panoptosubmission_activity_task.class.php
index 3dd47a3..966fef2 100644
--- a/backup/moodle2/restore_panoptosubmission_activity_task.class.php
+++ b/backup/moodle2/restore_panoptosubmission_activity_task.class.php
@@ -54,9 +54,9 @@ protected function define_my_steps() {
* Decode contents for restore
*/
public static function define_decode_contents() {
- $contents = array();
+ $contents = [];
- $contents[] = new restore_decode_content('panoptosubmission', array('intro'), 'panoptosubmission');
+ $contents[] = new restore_decode_content('panoptosubmission', ['intro'], 'panoptosubmission');
return $contents;
}
@@ -65,7 +65,7 @@ public static function define_decode_contents() {
* Decode rules for restore
*/
public static function define_decode_rules() {
- $rules = array();
+ $rules = [];
$rules[] = new restore_decode_rule('PANOPTOSUBMISSIONVIEWBYID', '/mod/panoptosubmission/view.php?id=$1', 'course_module');
$rules[] = new restore_decode_rule('PANOPTOSUBMISSIONINDEX', '/mod/panoptosubmission/index.php?id=$1', 'course');
@@ -78,7 +78,7 @@ public static function define_decode_rules() {
* log rules for restore
*/
public static function define_restore_log_rules() {
- $rules = array();
+ $rules = [];
$rules[] = new restore_log_rule('panoptosubmission', 'add', 'view.php?id={course_module}', '{panoptosubmission}');
$rules[] = new restore_log_rule('panoptosubmission', 'update', 'view.php?id={course_module}', '{panoptosubmission}');
@@ -91,7 +91,7 @@ public static function define_restore_log_rules() {
* Log rules for course during restore
*/
public static function define_restore_log_rules_for_course() {
- $rules = array();
+ $rules = [];
$rules[] = new restore_log_rule('panoptosubmission', 'view all', 'index.php?id={course}', null);
return $rules;
diff --git a/backup/moodle2/restore_panoptosubmission_stepslib.php b/backup/moodle2/restore_panoptosubmission_stepslib.php
index dc43ae2..cae5850 100644
--- a/backup/moodle2/restore_panoptosubmission_stepslib.php
+++ b/backup/moodle2/restore_panoptosubmission_stepslib.php
@@ -36,7 +36,7 @@ class restore_panoptosubmission_activity_structure_step extends restore_activity
* @return object The structure object
*/
protected function define_structure() {
- $paths = array();
+ $paths = [];
$userinfo = $this->get_setting_value('userinfo');
$paths[] = new restore_path_element('panoptosubmission', '/activity/panoptosubmission');
diff --git a/classes/event/assignment_details_viewed.php b/classes/event/assignment_details_viewed.php
index 1ea696f..7f20323 100644
--- a/classes/event/assignment_details_viewed.php
+++ b/classes/event/assignment_details_viewed.php
@@ -65,15 +65,6 @@ public function get_description() {
* @return string a url to the grade submission page
*/
public function get_url() {
- return new \moodle_url('/mod/panoptosubmission/view.php', array('cmid' => $this->contextinstanceid));
- }
-
- /**
- * returns an array of legacy log data
- * @return array a array used to store the legacy log data
- */
- public function get_legacy_logdata() {
- return array($this->courseid, 'panoptosubmission', 'view assignment details',
- $this->get_url(), $this->objectid, $this->contextinstanceid);
+ return new \moodle_url('/mod/panoptosubmission/view.php', ['id' => $this->contextinstanceid]);
}
}
diff --git a/classes/event/assignment_submitted.php b/classes/event/assignment_submitted.php
index 8457ea5..5fa8e89 100644
--- a/classes/event/assignment_submitted.php
+++ b/classes/event/assignment_submitted.php
@@ -65,15 +65,6 @@ public function get_description() {
* @return string a url to the grade submission page
*/
public function get_url() {
- return new \moodle_url('/mod/panoptosubmission/view.php', array('cmid' => $this->contextinstanceid));
- }
-
- /**
- * returns an array of legacy log data
- * @return array a array used to store the legacy log data
- */
- public function get_legacy_logdata() {
- return array($this->courseid, 'panoptosubmission', 'submit',
- $this->get_url(), $this->objectid, $this->contextinstanceid);
+ return new \moodle_url('/mod/panoptosubmission/view.php', ['id' => $this->contextinstanceid]);
}
}
diff --git a/classes/event/grade_submissions_page_viewed.php b/classes/event/grade_submissions_page_viewed.php
index c00c05b..d5d84d2 100644
--- a/classes/event/grade_submissions_page_viewed.php
+++ b/classes/event/grade_submissions_page_viewed.php
@@ -65,15 +65,6 @@ public function get_description() {
* @return string a url to the grade submission page
*/
public function get_url() {
- return new \moodle_url('/mod/panoptosubmission/grade_submissions.php', array('cmid' => $this->contextinstanceid));
- }
-
- /**
- * returns an array of legacy log data
- * @return array a array used to store the legacy log data
- */
- public function get_legacy_logdata() {
- return array($this->courseid, 'panoptosumission', 'view submissions page',
- $this->get_url(), $this->objectid, $this->contextinstanceid);
+ return new \moodle_url('/mod/panoptosubmission/grade_submissions.php', ['id' => $this->contextinstanceid]);
}
}
diff --git a/classes/event/grades_updated.php b/classes/event/grades_updated.php
index 097259e..b33cf83 100644
--- a/classes/event/grades_updated.php
+++ b/classes/event/grades_updated.php
@@ -64,15 +64,6 @@ public function get_description() {
* @return string a url to the grade submission page
*/
public function get_url() {
- return new \moodle_url('/mod/panoptosubmission/grade_submissions.php', array('cmid' => $this->contextinstanceid));
- }
-
- /**
- * returns an array of legacy log data
- * @return array a array used to store the legacy log data
- */
- public function get_legacy_logdata() {
- return array($this->courseid, 'panoptosubmission', 'update grades',
- $this->get_url(), $this->contextinstanceid);
+ return new \moodle_url('/mod/panoptosubmission/grade_submissions.php', ['id' => $this->contextinstanceid]);
}
}
diff --git a/classes/event/single_submission_page_viewed.php b/classes/event/single_submission_page_viewed.php
index 1707f4c..cbca73b 100644
--- a/classes/event/single_submission_page_viewed.php
+++ b/classes/event/single_submission_page_viewed.php
@@ -65,15 +65,6 @@ public function get_description() {
* @return string a url to the grade submission page
*/
public function get_url() {
- return new \moodle_url('/mod/panoptosubmission/single_submission.php', array('cmid' => $this->contextinstanceid));
- }
-
- /**
- * returns an array of legacy log data
- * @return array a array used to store the legacy log data
- */
- public function get_legacy_logdata() {
- return array($this->courseid, 'panoptosubmission', 'view submission page',
- $this->get_url(), $this->objectid, $this->contextinstanceid);
+ return new \moodle_url('/mod/panoptosubmission/single_submission.php', ['id' => $this->contextinstanceid]);
}
}
diff --git a/classes/grades/gradeitems.php b/classes/grades/gradeitems.php
index 310fdd4..c7eb738 100644
--- a/classes/grades/gradeitems.php
+++ b/classes/grades/gradeitems.php
@@ -26,8 +26,8 @@
namespace mod_panoptosubmission\grades;
-use \core_grades\local\gradeitem\itemnumber_mapping;
-use \core_grades\local\gradeitem\advancedgrading_mapping;
+use core_grades\local\gradeitem\itemnumber_mapping;
+use core_grades\local\gradeitem\advancedgrading_mapping;
/**
* Grade item mappings for the activity.
diff --git a/classes/privacy/provider.php b/classes/privacy/provider.php
index 7fee0a7..89748ea 100644
--- a/classes/privacy/provider.php
+++ b/classes/privacy/provider.php
@@ -43,14 +43,14 @@ class provider implements \core_privacy\local\metadata\provider,
* @param collection $collection the object used to store and return the privacy definitions
* @return returns the collection that includes the new privacy definitions
*/
- public static function get_metadata(collection $collection) : collection {
+ public static function get_metadata(collection $collection): collection {
$collection->add_external_location_link(
'panoptosubmission_submission',
[
'userid' => 'privacy:metadata:panoptosubmission_submission:userid',
'username' => 'privacy:metadata:panoptosubmission_submission:username',
- 'email' => 'privacy:metadata:panoptosubmission_submission:email'
+ 'email' => 'privacy:metadata:panoptosubmission_submission:email',
],
'privacy:metadata:panoptosubmission_submission'
);
@@ -68,7 +68,7 @@ public static function get_metadata(collection $collection) : collection {
'mailed' => 'privacy:metadata:panoptosubmission_submission:mailed',
'timemarked' => 'privacy:metadata:panoptosubmission_submission:timemarked',
'timecreated' => 'privacy:metadata:panoptosubmission_submission:timecreated',
- 'timemodified' => 'privacy:metadata:panoptosubmission_submission:timemodified'
+ 'timemodified' => 'privacy:metadata:panoptosubmission_submission:timemodified',
],
'privacy:metadata:panoptosubmission_submission'
);
@@ -101,7 +101,7 @@ public static function export_user_preferences(int $userid) {
'panoptosubmission_group_filter' => get_string(
'privacy:metadata:panoptosubmissiongroupfilter', 'mod_panoptosubmission'),
'panoptosubmission_perpage' => get_string('privacy:metadata:panoptosubmissionperpage', 'mod_panoptosubmission'),
- 'panoptosubmission_quickgrade' => get_string('privacy:metadata:panoptosubmissionquickgrade', 'mod_panoptosubmission')
+ 'panoptosubmission_quickgrade' => get_string('privacy:metadata:panoptosubmissionquickgrade', 'mod_panoptosubmission'),
];
foreach ($assignmentpreferences as $key => $preferencestring) {
@@ -120,7 +120,7 @@ public static function export_user_preferences(int $userid) {
* @param int $userid The user to search.
* @return contextlist $contextlist The list of contexts used in this plugin.
*/
- public static function get_contexts_for_userid(int $userid) : contextlist {
+ public static function get_contexts_for_userid(int $userid): contextlist {
$contextlist = new \core_privacy\local\request\contextlist();
$sql = "SELECT DISTINCT ctx.id FROM {context} ctx " .
@@ -135,7 +135,7 @@ public static function get_contexts_for_userid(int $userid) : contextlist {
'modulename' => 'panoptosubmission',
'contextlevel' => CONTEXT_MODULE,
'userid' => $userid,
- 'teacher' => $userid
+ 'teacher' => $userid,
];
$contextlist->add_from_sql($sql, $params);
@@ -158,7 +158,7 @@ public static function get_users_in_context(userlist $userlist) {
$params = [
'modulename' => 'panoptosubmission',
'contextlevel' => CONTEXT_MODULE,
- 'contextid' => $context->id
+ 'contextid' => $context->id,
];
$sql = "SELECT s.userid FROM {panoptosubmission_submission} s " .
@@ -218,16 +218,14 @@ public static function export_user_data(approved_contextlist $contextlist) {
$controller = $gradingmanager->get_active_controller();
foreach ($submissionsdata as $submissiondata) {
// Default subcontext path to export assignment submissions submitted by the user.
- $subcontexts = [
- get_string('privacy:submissionpath', 'mod_panoptosubmission')
- ];
+ $subcontexts = [get_string('privacy:submissionpath', 'mod_panoptosubmission')];
if ($teacher == true) {
if ($submissiondata->teacher == $user->id) {
// Export panoptosubmission submissions that have been marked by the user.
$subcontexts = [
get_string('privacy:markedsubmissionspath', 'mod_panoptosubmission'),
- transform::user($submissiondata->userid)
+ transform::user($submissiondata->userid),
];
}
}
@@ -271,6 +269,10 @@ public static function delete_data_for_all_users_in_context(\context $context) {
if (isset($controller)) {
\core_grading\privacy\provider::delete_instance_data($context);
}
+
+ // Delete all panoptosubmission files.
+ $fs = get_file_storage();
+ $fs->delete_area_files($context->id, STUDENTSUBMISSION_FILE_COMPONENT, STUDENTSUBMISSION_FILE_FILEAREA);
}
/**
@@ -363,7 +365,7 @@ protected static function get_panoptosubmission_submissions_by_contextlist($cont
$params = [
'contextlevel' => CONTEXT_MODULE,
'modulename' => 'panoptosubmission',
- 'userid' => $userid
+ 'userid' => $userid,
];
$sql = "SELECT s.id as id, " .
@@ -401,7 +403,7 @@ protected static function get_panoptosubmission_by_context($context) {
$params = [
'modulename' => 'panoptosubmission',
'contextmodule' => CONTEXT_MODULE,
- 'contextid' => $context->id
+ 'contextid' => $context->id,
];
$sql = "SELECT a.id, " .
@@ -432,7 +434,7 @@ protected static function get_panoptosubmission_output($panoptosubmissiondata) {
'name' => $panoptosubmissiondata->name,
'intro' => $panoptosubmissiondata->intro,
'grade' => $panoptosubmissiondata->grade,
- 'timemodified' => transform::datetime($panoptosubmissiondata->timemodified)
+ 'timemodified' => transform::datetime($panoptosubmissiondata->timemodified),
];
if ($panoptosubmissiondata->timeavailable != 0) {
@@ -463,7 +465,7 @@ protected static function has_marked_panoptosubmission_submissions($panoptosubmi
$params = [
'panactivityid' => $panoptosubmissionid,
- 'teacher' => $userid
+ 'teacher' => $userid,
];
$sql = "SELECT count(s.id) as nomarked " .
@@ -491,7 +493,7 @@ protected static function get_panoptosubmission_submissions_by_panoptosubmission
$params = [
'panactivityid' => $panoptosubmissionid,
- 'userid' => $userid
+ 'userid' => $userid,
];
$sql = "SELECT s.id as id, " .
@@ -530,7 +532,7 @@ protected static function get_panoptosubmission_submission_output($submissiondat
'source' => $submissiondata->source,
'grade' => $submissiondata->grade,
'submissioncomment' => $submissiondata->submissioncomment,
- 'teacher' => transform::user($submissiondata->teacher)
+ 'teacher' => transform::user($submissiondata->teacher),
];
if ($submissiondata->timecreated != 0) {
diff --git a/classes/renderable/panoptosubmission_course_index_summary.php b/classes/renderable/panoptosubmission_course_index_summary.php
index 9bf1fd4..17df205 100644
--- a/classes/renderable/panoptosubmission_course_index_summary.php
+++ b/classes/renderable/panoptosubmission_course_index_summary.php
@@ -27,8 +27,8 @@
*/
class panoptosubmission_course_index_summary implements renderable {
/** @var array activities A list of course modules and their status or submission counts depending on the user capabilities */
- public $activities = array();
- /** @var boolean usesections True if the parent course supports sections */
+ public $activities = [];
+ /** @var bool usesections True if the parent course supports sections */
public $usesections = false;
/** @var string courseformat The current course format name */
public $courseformatname = '';
@@ -45,7 +45,7 @@ public function __construct($usesections, $courseformatname) {
}
/**
- * Adds information for an activity on the acitivity index page
+ * Adds information for an activity on the activity index page
*
* @param int $cmid The course module id of the activity
* @param string $cmname The name of the activity
@@ -56,13 +56,13 @@ public function __construct($usesections, $courseformatname) {
* @param string $gradeinfo The current users grade if the activity has been graded.
*/
public function add_assign_info($cmid, $cmname, $sectionname, $timedue, $submissioninfo, $gradeinfo) {
- $this->activities[] = array(
+ $this->activities[] = [
'cmid' => $cmid,
'cmname' => $cmname,
'sectionname' => $sectionname,
'timedue' => $timedue,
'submissioninfo' => $submissioninfo,
- 'gradeinfo' => $gradeinfo
- );
+ 'gradeinfo' => $gradeinfo,
+ ];
}
}
diff --git a/classes/renderable/panoptosubmission_grading_summary.php b/classes/renderable/panoptosubmission_grading_summary.php
index 4356f36..7572b03 100644
--- a/classes/renderable/panoptosubmission_grading_summary.php
+++ b/classes/renderable/panoptosubmission_grading_summary.php
@@ -46,11 +46,11 @@ class panoptosubmission_grading_summary implements renderable {
public $timelimit = 0;
/** @var int coursemoduleid - The submission course module id */
public $coursemoduleid = 0;
- /** @var boolean relativedatesmode - Is the course a relative dates mode course or not */
+ /** @var bool relativedatesmode - Is the course a relative dates mode course or not */
public $courserelativedatesmode = false;
/** @var int coursestartdate - start date of the course as a unix timestamp*/
public $coursestartdate;
- /** @var boolean isvisible - Is the submission's context module visible to students? */
+ /** @var bool isvisible - Is the submission's context module visible to students? */
public $isvisible = true;
/**
diff --git a/contentitem.php b/contentitem.php
index 848d739..87b79c4 100644
--- a/contentitem.php
+++ b/contentitem.php
@@ -78,7 +78,7 @@
$returnurlparams = [
'course' => $course->id,
'id' => $toolid,
- 'sesskey' => sesskey()
+ 'sesskey' => sesskey(),
];
$returnurl = new \moodle_url(STUDENT_SUBMISSION_PATH, $returnurlparams);
diff --git a/contentitem_return.php b/contentitem_return.php
index 21ad092..1ea687a 100644
--- a/contentitem_return.php
+++ b/contentitem_return.php
@@ -95,7 +95,7 @@
$title = "";
$itemtitle = $contentitems->{'@graph'}[0]->title;
if (!empty($itemtitle)) {
- $invalidcharacters = array("$", "%", "#", "<", ">");
+ $invalidcharacters = ["$", "%", "#", "<", ">"];
$cleantitle = str_replace($invalidcharacters, "", $itemtitle);
$title = is_string($cleantitle) ? $cleantitle : $title;
}
@@ -127,32 +127,33 @@
?>