Skip to content

Commit 8a6b12e

Browse files
committed
WR455936: Group submissions
WR455936: PR fixes
1 parent e97f2d6 commit 8a6b12e

16 files changed

+1385
-70
lines changed

README.md

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,42 @@ If the locking setting permits 'Unlock after grading':
144144

145145
If you need help, try the [Moodle-Mahara Integration forum](https://mahara.org/interaction/forum/view.php?id=30)
146146

147-
Submitting of group portfolios is not yet supported.
147+
Submitting of group portfolios
148+
---------------------------------
149+
When group submissions are enabled in the standard Moodle assignment settings, group portfolios can be submitted from Mahara to Moodle.
150+
151+
At site level, the institution short name for the global web service should be set. If global config is not set, the institution will be configured
152+
by the web service itself and displayed for information only in the assignment settings.
153+
154+
With group submissions enabled, a groups selector will appear underneath the other Mahara configuration options in the assignment settings.
155+
If global config is enabled the groups selector will be available when adding a new assignment, otherwise the selector
156+
will be available after the assignment has been initially created.
157+
158+
The groups available for selection will be any that haven't already been mapped to a Mahara group or those that are already linked to the currently configured
159+
Mahara web service institution.
160+
161+
Because there is the potential for different assignments to be linked to different institutions in one course, once groups
162+
have been selected for an assignment the web service configuration cannot be changed (unless all the groups are subsequently de-selected first).
163+
164+
When a group (or groups) is selected in an assignment, an adhoc task 'Create group' is created when the assignment settings
165+
are saved. A web service creates the group in Mahara and syncs all the group members at the same time; this is the only way a Moodle assignment group can be created in Mahara. When a group is created in
166+
Mahara it will be placed into a category called 'Moodle Managed Groups'; to change the name of this category, update the string 'groups:category' in the Moodle plugin.
167+
168+
Mahara group membership is also managed via Moodle. When a group name is changed or group members are added or removed, an adhoc task 'Sync member' is created . A web service will sync the
169+
changes to Mahara. If a group is deleted in Moodle the mapping is removed from Moodle but the group in Mahara is not deleted as we don't want to lose
170+
student work. The group name in Mahara will be updated to include the text 'deleted from Moodle'. Moodle assignment groups cannot be updated manually in Mahara.
171+
172+
Whenever a group is created or group membership is changed for a Mahara mapped group, an account will be created for a user if one doesn't already exist.
173+
174+
Students can only be a member of one of the groups that have been mapped in an assignment. This is to avoid the possibility of a student accidentally
175+
submitting work from the wrong Mahara group as this would give the other group members access to a portfolio they shouldn't be able to view.
176+
177+
When submitting a group portfolio, students will only be able to select group portfolios from the group they are a member of, for the assignment they are submitting to.
178+
Individual portfolios are not available for selection in group assignments.
179+
180+
Archiving of portfolios is not currently available for group submissions but otherwise all other functionality works the same as for individual submissions.
181+
182+
**Development of groups functionality was funded by Dublin City University (DCU), Ireland, through its DCU Futures initiative.**
148183

149184
Convert MNet submissions
150185
------------------------
@@ -179,6 +214,7 @@ The upgrade of the plugin to support web services has been done thanks to fundin
179214
* Waitematā District Health Board
180215
* Monash University
181216
* Catalyst IT
217+
* Dublin City University (DCU)
182218

183219
License
184220
-------

classes/helper.php

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
<?php
2+
// This file is part of Moodle - http://moodle.org/
3+
//
4+
// Moodle is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// Moodle is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU General Public License
15+
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
16+
17+
/**
18+
* Helper class.
19+
*
20+
* @package assignsubmission_maharaws
21+
* @author 2025 Sarah Cotton <sarah.cotton@catalyst-au.net>
22+
* @copyright Catalyst IT, 2025
23+
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24+
* */
25+
26+
namespace assignsubmission_maharaws;
27+
28+
use stdClass;
29+
30+
/**
31+
* Helper class.
32+
*/
33+
class helper {
34+
35+
/**
36+
* Get the Mahara group mapping record.
37+
*
38+
* @param int $moodlegroup The Moodle group id.
39+
* @return mixed a fieldset object containing the first matching record or false.
40+
*/
41+
public static function get_mahara_group(int $moodlegroup): mixed {
42+
global $DB;
43+
return $DB->get_record('assignsubmission_maharawsgroup', ['moodlegroup' => $moodlegroup]);
44+
}
45+
46+
/**
47+
* Create Mahara groups against the configured Mahara institution.
48+
*
49+
* @param stdClass $data The form data.
50+
*/
51+
public static function create_mahara_groups(stdClass $data): void {
52+
global $DB, $USER;
53+
54+
$groupids = $data->assignsubmission_maharaws_groups;
55+
if ($groupids) {
56+
$creategroups = [];
57+
$creategroupserrors = [];
58+
foreach ($groupids as $groupid) {
59+
$group = groups_get_group($groupid);
60+
61+
// Has the selected group already been created/mapped to a Mahara group?
62+
$maharagroup = self::get_mahara_group($group->id);
63+
// If not, schedule an adhoc task to try and create the group.
64+
if (!$maharagroup) {
65+
try {
66+
$task = \assignsubmission_maharaws\task\create_group::instance($group->courseid, $group->id, $USER->id);
67+
\core\task\manager::queue_adhoc_task($task, true);
68+
$creategroups[] = $group->name;
69+
70+
if (!$DB->get_record('assignsubmission_maharawsgroup', ['moodlegroup' => $group->id])) {
71+
// Store Moodle group id and institution.
72+
$obj = new stdClass();
73+
$obj->moodlegroup = $group->id;
74+
$obj->institution = $data->institution;
75+
$DB->insert_record('assignsubmission_maharawsgroup', $obj);
76+
}
77+
} catch (\Exception $e) {
78+
$creategroupserrors[] = $e->getMessage();
79+
}
80+
}
81+
}
82+
83+
if (!empty($creategroups)) {
84+
// Let the user know the groups have been queued for creation.
85+
\core\notification::add(get_string('groups:createdgroups', 'assignsubmission_maharaws',
86+
implode(', ', $creategroups)), \core\output\notification::NOTIFY_SUCCESS);
87+
}
88+
89+
if (!empty($creategroupserrors)) {
90+
// Let the user know of any errors.
91+
\core\notification::add(get_string('groups:createdgroups:errors', 'assignsubmission_maharaws',
92+
implode(', ', $creategroupserrors)), \core\output\notification::NOTIFY_ERROR);
93+
}
94+
}
95+
}
96+
97+
/**
98+
* Send error notification for sync job failures.
99+
*
100+
* @param int $userid User to send the notification to.
101+
* @param stdClass $course Course the notification is associated with.
102+
* @param string $messagebody The message.
103+
*/
104+
public static function send_notification(int $userid, stdClass $course, string $taskname, string $messagebody) {
105+
global $DB;
106+
107+
$message = new \core\message\message();
108+
$message->component = 'assignsubmission_maharaws';
109+
$message->name = $taskname;
110+
$message->userfrom = \core_user::get_noreply_user();
111+
$message->userto = $userid;
112+
$message->subject = get_string('messagesubject:'. $taskname, 'assignsubmission_maharaws', $course->fullname);
113+
$message->fullmessage = $messagebody;
114+
$message->fullmessageformat = FORMAT_MARKDOWN;
115+
$message->fullmessagehtml = $messagebody;
116+
$message->smallmessage = $messagebody;
117+
$message->notification = 1;
118+
$message->contexturl = (new \moodle_url('/course/view.php', ['id' => $course->id]))->out(false);
119+
$message->contexturlname = 'Course ' . $course->fullname;
120+
121+
// Extra content for specific processor.
122+
$content = [
123+
'*' => [
124+
'footer' => '<p>Link to course: ' . $message->contexturl . '</p>',
125+
],
126+
];
127+
$message->set_additional_content('email', $content);
128+
message_send($message);
129+
130+
// Additionally send the notification to admins.
131+
$admins = get_config('assignsubmission_maharaws', 'errornotifications');
132+
if ($admins !== '') {
133+
$admins = explode(',', $admins);
134+
foreach ($admins as $admin) {
135+
$userid = $DB->get_field('user', 'id', ['username' => trim($admin)]);
136+
$message->userto = $userid;
137+
message_send($message);
138+
}
139+
}
140+
}
141+
}

classes/hook_callbacks.php

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
<?php
2+
// This file is part of Moodle - http://moodle.org/
3+
//
4+
// Moodle is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// Moodle is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU General Public License
15+
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
16+
17+
namespace assignsubmission_maharaws;
18+
19+
use core\hook\output\after_http_headers;
20+
21+
/**
22+
* Hook callbacks for assignsubmission_maharaws.
23+
*
24+
* @package assignsubmission_maharaws
25+
* @author 2025 Sarah Cotton <sarah.cotton@catalyst-au.net>
26+
* @copyright Catalyst IT, 2025
27+
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
28+
*/
29+
class hook_callbacks {
30+
/**
31+
* Add sync task notifications to assignment or participants pages.
32+
*
33+
* @param after_http_headers $hook
34+
*/
35+
public static function after_http_headers(after_http_headers $hook): void {
36+
global $OUTPUT, $DB;
37+
if (has_capability('mod/assign:addinstance', $OUTPUT->get_page()->context, )) {
38+
// Check we're on the right page.
39+
$pagetype = $OUTPUT->get_page()->pagetype;
40+
if ($pagetype == 'mod-assign-view') {
41+
$classname = '\assignsubmission_maharaws\task\create_group';
42+
}
43+
if ($pagetype == 'course-view-participants') {
44+
$classname = '\assignsubmission_maharaws\task\sync_member';
45+
}
46+
47+
// Get any queued adhoc tasks for this course.
48+
if (isset($classname)) {
49+
$courseid = $OUTPUT->get_page()->course->id;
50+
$likecourseid = $DB->sql_like('customdata', ':customdata');
51+
$params = [
52+
'classname' => $classname,
53+
'customdata' => '%"courseid":' . $courseid . '%',
54+
];
55+
$tasks = $DB->get_records_sql("SELECT *
56+
FROM {task_adhoc}
57+
WHERE classname = :classname
58+
AND $likecourseid", $params
59+
);
60+
61+
// Count pending/failed tasks.
62+
if (count($tasks) > 0) {
63+
$pending = 0;
64+
$failed = 0;
65+
foreach ($tasks as $task) {
66+
if ($task->faildelay == 0) {
67+
$pending++;
68+
} else {
69+
$failed++;
70+
}
71+
}
72+
73+
// Output notification to the user.
74+
if (isset($tasks)) {
75+
$message = get_string('groups:syncnotification', 'assignsubmission_maharaws',
76+
['pending' => $pending, 'failed' => $failed]);
77+
$notification = $OUTPUT->render(new \core\output\notification($message,
78+
\core\output\notification::NOTIFY_WARNING));
79+
$hook->add_html($notification);
80+
}
81+
}
82+
}
83+
}
84+
}
85+
}

0 commit comments

Comments
 (0)