Moodle

Allow deadlines to be set on a per group basis

Details

  • Affected Branches:
    MOODLE_19_STABLE, MOODLE_21_STABLE

Description

This would make Moodle's use in our school almost flawless. Being able to set specific open and close times on a per group basis as well as different deadlines per group would allow courses that are taught at different speeds for different groups to run smoothly. At the moment, I'm either manually opening and closing the quizzes and assignment deadlines, or I'm making three identical assignments.

Issue Links

Activity

Hide
Matt Gibson added a comment -

Allowing per-group deadlines is critical for anyone who uses the same course to teach more than one group on slightly different timetables. Without it, the deadlines data in the gradebook is severey limited. I would imagine this applies to almost every school teacher using Moodle, so it's a big deal.

Show
Matt Gibson added a comment - Allowing per-group deadlines is critical for anyone who uses the same course to teach more than one group on slightly different timetables. Without it, the deadlines data in the gradebook is severey limited. I would imagine this applies to almost every school teacher using Moodle, so it's a big deal.
Hide
Matt Petro added a comment -

Flexible due dates are critical to us as well, so I've developed a patch for moodle 2.0 that adds quiz overrides on a per-user and per-group basis. Currently quiz open, quiz close and timelimit are configurable.

Overview:

  • Adds an extra database table linking from a quiz to user/group giving timeopen, timeclose, timelimit overrides
  • Adds a user-interface tab to the quiz editing page for controlling the settings.
  • Adds code to populate per-user and per-group events based on the overrides

New functions in mod/quiz/lib.php:
quiz_delete_override()
quiz_delete_all_overrides()
quiz_compute_effective_override() // compute effective due dates, etc for a particular user
quiz_events_update() // moved event processing code to here to avoid duplication

New functions in quiz class (attemptlib):
get_effective_timeopen() // return data computed for a particular user
get_effective_timeclose()
get_effective_timelimit()

New files:
mod/quiz/override.php // override editing page
mod/quiz/override_form.php // editing form

TODO:

  • No backup/restore of overrides (but this code won't break quiz backup/restore)
  • quiz_compute_effective_override() is called more often than necessary. Some code refactoring could fix this by passing around the per-user override information to various calls.
  • Work on the events interface, so that students don't see the default quiz open/close when an override is in place. I'm not sure on this one, and it will probably involve changing the calentar events code.

I'd be glad to work with someone to get these changes added to trunk.

Show
Matt Petro added a comment - Flexible due dates are critical to us as well, so I've developed a patch for moodle 2.0 that adds quiz overrides on a per-user and per-group basis. Currently quiz open, quiz close and timelimit are configurable. Overview:
  • Adds an extra database table linking from a quiz to user/group giving timeopen, timeclose, timelimit overrides
  • Adds a user-interface tab to the quiz editing page for controlling the settings.
  • Adds code to populate per-user and per-group events based on the overrides
New functions in mod/quiz/lib.php: quiz_delete_override() quiz_delete_all_overrides() quiz_compute_effective_override() // compute effective due dates, etc for a particular user quiz_events_update() // moved event processing code to here to avoid duplication New functions in quiz class (attemptlib): get_effective_timeopen() // return data computed for a particular user get_effective_timeclose() get_effective_timelimit() New files: mod/quiz/override.php // override editing page mod/quiz/override_form.php // editing form TODO:
  • No backup/restore of overrides (but this code won't break quiz backup/restore)
  • quiz_compute_effective_override() is called more often than necessary. Some code refactoring could fix this by passing around the per-user override information to various calls.
  • Work on the events interface, so that students don't see the default quiz open/close when an override is in place. I'm not sure on this one, and it will probably involve changing the calentar events code.
I'd be glad to work with someone to get these changes added to trunk.
Hide
Matt Petro added a comment -

This patch will also close http://tracker.moodle.org/browse/MDL-16808

Could someone with privs edit the affected versions to include moodle 2.0? Thanks.

Show
Matt Petro added a comment - This patch will also close http://tracker.moodle.org/browse/MDL-16808 Could someone with privs edit the affected versions to include moodle 2.0? Thanks.
Hide
Matt Petro added a comment -
Show
Matt Petro added a comment - Rather, http://tracker.moodle.org/browse/MDL-16478
Hide
Tim Hunt added a comment -

Have not looked at the code yet.

Backup and restore is essential before this can go into CVS.

The calendar one is tricky. Presumably we need to create group and user events, rather than course, events, depending on the settings.

Show
Tim Hunt added a comment - Have not looked at the code yet. Backup and restore is essential before this can go into CVS. The calendar one is tricky. Presumably we need to create group and user events, rather than course, events, depending on the settings.
Hide
Matt Petro added a comment -

I can work on the backup/restore code.

For the calendar events, I see two possibilities:

1. In calendar_get_events(), use logic like this:

Group all matching events into groups with the same modulename, instance, and eventtype.
Return one representative from each group based on the preference order: user, group, course event

I'm not sure if this would break other users of the calendar or not.

2. Add a column that can be used to group entries. For example, 'parent'. Then apply the logic from above,
but only group according to the same 'parent'. Do you have any idea what the uuid and sequence columns in the event table are?

Show
Matt Petro added a comment - I can work on the backup/restore code. For the calendar events, I see two possibilities: 1. In calendar_get_events(), use logic like this: Group all matching events into groups with the same modulename, instance, and eventtype. Return one representative from each group based on the preference order: user, group, course event I'm not sure if this would break other users of the calendar or not. 2. Add a column that can be used to group entries. For example, 'parent'. Then apply the logic from above, but only group according to the same 'parent'. Do you have any idea what the uuid and sequence columns in the event table are?
Hide
Matt Petro added a comment -

Backup/restore patch attached

Show
Matt Petro added a comment - Backup/restore patch attached
Hide
Tim Hunt added a comment -

Thank you very much for working on this. As you can see from the number of votes on MDL-16478, a lot of people want this. Also, since your post in the general developer forum, I have seen two posts in the quiz forum asking for this.

Some code review comments:

(I wrote these in one order as a reviewed the code, the re-ordered them to put the more important ones first. I hope that does not make it incomprehensible.)

0. Generally it looks very good. (As you can tell from the very picky nature of most of the comments below.)

1. In the database, the userid and groupid columns should be nullable, and they should be foreign keys.

2. Also, I think that timeopen, etc. should be nullable, so you can distinguish between allowing a user to attempt the quiz with no close date or time limit (value 0) from not overriding the default (value null).

3. I have previously seen feature requests to have different passwords per-group. You might like to include that, but one of the nice things about your work is that it is easy to extend in future.

4. I don't like a single, multi-modal override.php script. It would be cleaner to have three short scripts overrides.php for the list. overrideedit.php for add/edit, and overridedelete.php for the delete confirmation and action.

5. I see you have coped with users in multiple groups by taking the most permissive overrides. That seems sensible to me.

6. In attemptlib.php. Is it really necessary to have a separate protected $override; ? Why not just overwrite the default values in $this->quiz with the appropriate overridden values. Wouldn't that simplify things? For example, it would no longer be necessary to make so many changes to accessrules.php (although, arguably the changes you made to use methods on quizobj rather than directly accessing $quiz are good - I just wonder if it really helps to have the word effective_ everywhere.

7. I don't like big long if statements like if (!$override) { in quiz_compute_effective_override. See http://www.refactoring.com/catalog/replaceNestedConditionalWithGuardClauses.html. To do that here, you probably need to break the big function into some smaller ones, which would be a good idea anyway. 8. You should not concatenate language string like $overridename .= ' - '.groups_get_group_name($groupid).' '; That does not work for languages that use a different word order. The correct approach is to make another language string with $a->thing placeholders that get subsituted by the bits. 9. In Moodle 2.0, you don't need code like {code}
if ($events = $DB->get_records('event', array('modulename'=>'quiz', 'instance'=>$quiz->id, 'groupid'=>$groupid, 'userid'=>$userid))) {
foreach($events as $event) { {code}
any more. Instead you can just do



$events = $DB->get_records('event', array('modulename'=>'quiz', 'instance'=>$quiz->id, 'groupid'=>$groupid, 'userid'=>$userid));
foreach($events as $event) {{code}}
since get_records throws an exception on error, and returns an empty array if no records are found.

10. I don't see any point in @global object PHP doc tags. They say nothing. It would be nice (but not essential, if you could delete them.) You also have some incomplete PHP doc comments, like @return bool with no description of what the bool means. Again, nice if you can fix those.

11. Again being picky, but I feel that quiz_compute_effective_override is not the best name for this function. What you are actually computing is the effective access settings.

12. Personally, I hate the ? : operator, and the Moodle coding style guidelines recommends against it. However, again I don't insist on you making the change.

Once again, this is very good quality code. I would like to get this into Moodle 2.0. I am not sure how much time I will have to contribute to that, but I will try my best, if you can address some of the above issues.

Can I suggest that we move future patches/discussion to MDL-16478, since that is actually the bug about implementing this in the quiz. This bug is about the Assignment module. Thanks.

Show
Tim Hunt added a comment - Thank you very much for working on this. As you can see from the number of votes on MDL-16478, a lot of people want this. Also, since your post in the general developer forum, I have seen two posts in the quiz forum asking for this. Some code review comments: (I wrote these in one order as a reviewed the code, the re-ordered them to put the more important ones first. I hope that does not make it incomprehensible.) 0. Generally it looks very good. (As you can tell from the very picky nature of most of the comments below.) 1. In the database, the userid and groupid columns should be nullable, and they should be foreign keys. 2. Also, I think that timeopen, etc. should be nullable, so you can distinguish between allowing a user to attempt the quiz with no close date or time limit (value 0) from not overriding the default (value null). 3. I have previously seen feature requests to have different passwords per-group. You might like to include that, but one of the nice things about your work is that it is easy to extend in future. 4. I don't like a single, multi-modal override.php script. It would be cleaner to have three short scripts overrides.php for the list. overrideedit.php for add/edit, and overridedelete.php for the delete confirmation and action. 5. I see you have coped with users in multiple groups by taking the most permissive overrides. That seems sensible to me. 6. In attemptlib.php. Is it really necessary to have a separate protected $override; ? Why not just overwrite the default values in $this->quiz with the appropriate overridden values. Wouldn't that simplify things? For example, it would no longer be necessary to make so many changes to accessrules.php (although, arguably the changes you made to use methods on quizobj rather than directly accessing $quiz are good - I just wonder if it really helps to have the word effective_ everywhere. 7. I don't like big long if statements like if (!$override) { in quiz_compute_effective_override. See http://www.refactoring.com/catalog/replaceNestedConditionalWithGuardClauses.html. To do that here, you probably need to break the big function into some smaller ones, which would be a good idea anyway. 8. You should not concatenate language string like $overridename .= ' - '.groups_get_group_name($groupid).' '; That does not work for languages that use a different word order. The correct approach is to make another language string with $a->thing placeholders that get subsituted by the bits. 9. In Moodle 2.0, you don't need code like {code} if ($events = $DB->get_records('event', array('modulename'=>'quiz', 'instance'=>$quiz->id, 'groupid'=>$groupid, 'userid'=>$userid))) { foreach($events as $event) { {code} any more. Instead you can just do

$events = $DB->get_records('event', array('modulename'=>'quiz', 'instance'=>$quiz->id, 'groupid'=>$groupid, 'userid'=>$userid)); foreach($events as $event) {{code}} since get_records throws an exception on error, and returns an empty array if no records are found. 10. I don't see any point in @global object PHP doc tags. They say nothing. It would be nice (but not essential, if you could delete them.) You also have some incomplete PHP doc comments, like @return bool with no description of what the bool means. Again, nice if you can fix those. 11. Again being picky, but I feel that quiz_compute_effective_override is not the best name for this function. What you are actually computing is the effective access settings. 12. Personally, I hate the ? : operator, and the Moodle coding style guidelines recommends against it. However, again I don't insist on you making the change. Once again, this is very good quality code. I would like to get this into Moodle 2.0. I am not sure how much time I will have to contribute to that, but I will try my best, if you can address some of the above issues. Can I suggest that we move future patches/discussion to MDL-16478, since that is actually the bug about implementing this in the quiz. This bug is about the Assignment module. Thanks.
Hide
Petr Škoda (skodak) added a comment - - edited

I never liked groupmembersonly hack that people use to set up 10 separate assignments only to have different deadline - I came with a solution to have separate group mode deadlines/activity settings. And today I found this old bug, great!

It would be great to gets this implemented in an general way for 2.2, this may also affect following areas:

  • gradebook - due dates visualisation (missing in current gradebook)
  • calendar - the calendar code is a mess and the UI is not nice at all, all date handling routines need rewrite anyway
  • conditional activities - ? (so far I was ignoring this part completely)
  • group internals/UI - clean up when group deleted

Thanks!!

Show
Petr Škoda (skodak) added a comment - - edited I never liked groupmembersonly hack that people use to set up 10 separate assignments only to have different deadline - I came with a solution to have separate group mode deadlines/activity settings. And today I found this old bug, great! It would be great to gets this implemented in an general way for 2.2, this may also affect following areas:
  • gradebook - due dates visualisation (missing in current gradebook)
  • calendar - the calendar code is a mess and the UI is not nice at all, all date handling routines need rewrite anyway
  • conditional activities - ? (so far I was ignoring this part completely)
  • group internals/UI - clean up when group deleted
Thanks!!
Hide
Tim Hunt added a comment -

1. Do have a look at how this is implemented in the quiz. It is really surprisingly simple. All you do is, when you load the mdl_quiz row, also look to see if there are any overrides for the users's group, and if so, you use those overrides to update the $quiz object. Then all the rest of the quiz code stays the same, it just uses the udpated $quiz record.

I assume the same approach would work for other activities. The only difficulty is bulk operations (so, possibly, forum mail-outs). There, you suddenly need to allow for different $forum settings for different users - if that is relevant. There is currently a bug in quiz regrade because of this issue.

2. However, groupmembersonly is used for many purposes, not just to allow different deadlines for different groups. I can't remember all the things we use if for at the OU. The person to ask is Sam Marshall. I suggest you talk to him to get some typical use-cases to help you plan how to replace groupmembersonly - if that is your intention.

Show
Tim Hunt added a comment - 1. Do have a look at how this is implemented in the quiz. It is really surprisingly simple. All you do is, when you load the mdl_quiz row, also look to see if there are any overrides for the users's group, and if so, you use those overrides to update the $quiz object. Then all the rest of the quiz code stays the same, it just uses the udpated $quiz record. I assume the same approach would work for other activities. The only difficulty is bulk operations (so, possibly, forum mail-outs). There, you suddenly need to allow for different $forum settings for different users - if that is relevant. There is currently a bug in quiz regrade because of this issue. 2. However, groupmembersonly is used for many purposes, not just to allow different deadlines for different groups. I can't remember all the things we use if for at the OU. The person to ask is Sam Marshall. I suggest you talk to him to get some typical use-cases to help you plan how to replace groupmembersonly - if that is your intention.
Hide
Petr Škoda (skodak) added a comment -

1. forum/news/data should not be imo a big problem if you use separate group mode; ratings and comments could use separate controls for each group, this functionality should be handled by the core code and activities should not care about it (there is a lot of work left in these two subsystems)

2. Yes, we have already discussed with Sam the possibility to use capabilities for removing of activities from the course layout - for example special resources and forums for tutors only. I will try to contact him next week.

I am not sure hacking the $quiz object on the fly is the best way, maybe we could wrap it in some class, I think mod/workshop is doing it already - maybe David could share his experience with this solution.

Show
Petr Škoda (skodak) added a comment - 1. forum/news/data should not be imo a big problem if you use separate group mode; ratings and comments could use separate controls for each group, this functionality should be handled by the core code and activities should not care about it (there is a lot of work left in these two subsystems) 2. Yes, we have already discussed with Sam the possibility to use capabilities for removing of activities from the course layout - for example special resources and forums for tutors only. I will try to contact him next week. I am not sure hacking the $quiz object on the fly is the best way, maybe we could wrap it in some class, I think mod/workshop is doing it already - maybe David could share his experience with this solution.
Hide
James Cracknell added a comment -

Workshop will not allow view sorts by Group when you are looking at who is commenting on which assignment.

Could I ask that Moodle 2.1 is added to the version list please as it currently says 1.9 and I'd like to see it in 2.1+

Show
James Cracknell added a comment - Workshop will not allow view sorts by Group when you are looking at who is commenting on which assignment. Could I ask that Moodle 2.1 is added to the version list please as it currently says 1.9 and I'd like to see it in 2.1+
Hide
Petr Škoda (skodak) added a comment -

Please do not use this issue for unrelated requests, thanks.

Show
Petr Škoda (skodak) added a comment - Please do not use this issue for unrelated requests, thanks.
Hide
Tim Hunt added a comment -

Well, this is the total implementation for the quiz. I was surprised how little code it took. I agree we should more often be using real classes for things, but the basic principle - have a class to represent the activity and its settings - and then all you have to do to implement per-group or per-user setting overrides is to initialise the class different, should easily generalise to all activities. It means that you only have to worry about the overrides when initialising the class. (and, obviously, more UI for editing the overrides.)

Show
Tim Hunt added a comment - Well, this is the total implementation for the quiz. I was surprised how little code it took. I agree we should more often be using real classes for things, but the basic principle - have a class to represent the activity and its settings - and then all you have to do to implement per-group or per-user setting overrides is to initialise the class different, should easily generalise to all activities. It means that you only have to worry about the overrides when initialising the class. (and, obviously, more UI for editing the overrides.)
Hide
Petr Škoda (skodak) added a comment -

Yes, let's hope we gent enough votes to get attention from Martin and Michael or maybe we could find some organisation like OU that would like this improvement and would implement it.

Show
Petr Škoda (skodak) added a comment - Yes, let's hope we gent enough votes to get attention from Martin and Michael or maybe we could find some organisation like OU that would like this improvement and would implement it.
Hide
Jennifer L Chandler added a comment -

What exactly does the attachment quiz_override_patch do?

Show
Jennifer L Chandler added a comment - What exactly does the attachment quiz_override_patch do?
Hide
Matt Petro added a comment -

Implements overrides for quiz settings. It's already part of 2.0.

Show
Matt Petro added a comment - Implements overrides for quiz settings. It's already part of 2.0.

People

Dates

  • Created:
    Updated: