Augsburg moodle modifications

protecting idnumber in courses

Because enrollment is based on the idnumber field, we don't want faculty to change the idnumber field in their course or else enrollment might stop working. This is done by changing course/edit.html as shown below so that only admins can edit the field.

<?php
if( isadmin()){
echo "<td><input type=\"text\" name=\"idnumber\" maxlength=\"100\" size=\"10\" value=\"".$form->idnumber."\" alt=\"".print_string("idnumber")."\" />";
} else {
echo "<td><input type=\"hidden\" name=\"idnumber\" value=\"".$form->idnumber."\">".$form->idnumber;
}
?>

This is done where you find the usual <td><input type=\"text\" name=\"idnumber\" maxlength=\"100\" size=\"10\" value=\"".$form->idnumber."\" alt=\"".print_string("idnumber")."\" /> line.

preventing students from disabling email from moodle

It might be the case that you want to not allow students to disable receiving emails from moodle. You can do this by editing user/edit.html as below. At line 119 or so where the row for emailstop starts replace that row with this statement.

<?php if (isadmin()) {
echo "<tr><th>";
print_string("emailactive");
echo "</th><td>";
unset($choices);
$choices["0"] = get_string("emailenable");
$choices["1"] = get_string("emaildisable");
choose_from_menu ($choices, "emailstop", $user->emailstop, "");
echo "</td></tr>"; }
?>

So only admins will see the form item to change the emailstop for a user. Users will not even see the option in their profile page.

changing default values

Because some of the default values in moodle aren't what we want, we like to change them. Once you find where they are it makes it easier.

Rather than 'News Forum' we prefer 'Announcements' and students can't reply

In forum_get_course_forum in mod/forum/lib.php change
case "news":
$forum->name = addslashes(get_string("namenews", "forum"));

to

case "news":
$forum->name = "Announcements";

and

$forum->open = 1; // 0 - no, 1 - posts only, 2 - discuss and post

to

$forum->open = 0; // 0 - no, 1 - posts only, 2 - discuss and post

Rather than 100 pts as the maximum for assignments, we'd like 200.

In lib/weblib.php change function print_grade_menu
for ($i=100; $i>=1; $i--) {
$grades[$i] = $i;

to

for ($i=200; $i>=1; $i--) {
$grades[$i] = $i;

Rather than the usual default block setup, we'd like our own. This is much easier in 1.5.

In course/format/*/config.php change
$format['defaultblocks'] = 'participants,activity_modules,search_forums,'.
'admin,course_list:news_items,calendar_upcoming,'.
'recent_activity';

to

$format['defaultblocks'] = 'news_items,activity_modules,course_docs,'.
' compose_mail,calendar,online_users,participants,search_forums,admin';

You'll notice that at the moment our blocks are all on the left (the : is the delimiter between left and right).

We'd like online text assignments to default to comment inline = 'yes'

In mod/assignment/type/online/mod.html change
line 41: $options[0] = get_string("no"); $options[1] = get_string("yes");

to

$options[0] = get_string("yes"); $options[1] = get_string("no");

LDAP objectclass authentication patch 

Our primary web programmer noticed something was missing from the LDAP authentication plug-in when we were doing our integration work. In auth/ldap/lib.php change function auth_ldap_find_userdn from

if ($CFG->ldap_search_sub){
//use ldap_search to find first user from subtree
$ldap_result = ldap_search($ldapconnection, $context, "(".$CFG->ldap_user_attribute."=".$username.")",array($CFG->ldap_user_attribute));
} else {
//search only in this context
$ldap_result = ldap_list($ldapconnection, $context, "(".$CFG->ldap_user_attribute."=".$username.")",array($CFG->ldap_user_attribute));
}

to

/* Begin pre-patch code
if ($CFG->ldap_search_sub){
//use ldap_search to find first user from subtree
$ldap_result = ldap_search($ldapconnection, $context, "(".$CFG->ldap_user_attribute."=".$username.")",array($CFG->ldap_user_attribute));
} else {
//search only in this context
$ldap_result = ldap_list($ldapconnection, $context, "(".$CFG->ldap_user_attribute."=".$username.")",array($CFG->ldap_user_attribute));
}
End Pre-patch code */
// Begin patch to add ldap_objectclass config variable to user search filter
if (! isset($CFG->ldap_objectclass)) {
$CFG->ldap_objectclass="objectClass=inetOrgPerson";
}
$filter = "(&(".$CFG->ldap_user_attribute."=".$username.")(".$CFG->ldap_objectclass."))";

if ($CFG->ldap_search_sub){
//use ldap_search to find first user from subtree
$ldap_result = ldap_search($ldapconnection, $context, $filter, array($CFG->ldap_user_attribute));
} else {
//search only in this context
$ldap_result = ldap_list($ldapconnection, $context, $filter, array($CFG->ldap_user_attribute));
}
// End patch to add ldap_objectclass config variable to user search filter

gradebook changes

It seemed odd to some of our faculty that the gradebook links take you the main assignment page rather than the grading page. While I can see why it would be good for abstraction of assignment-like objects, it just annoys my faculty. So I changed it. In grade/lib.php change

line 1704 from
$link = $CFG->wwwroot.'/mod/'.$all_categories[$category][$assignment]['modname'].'/view.php?id='.$link_id->id;

to

// make links more grade-entry happy

if (isteacher($course->id)) {
if ($all_categories[$category][$assignment]['modname'] == 'assignment') {
$link = $CFG->wwwroot.'/mod/'.$all_categories[$category][$assignment]['modname'].'/submissions.php?id='.$link_id->id;
}
else if ($all_categories[$category][$assignment]['modname'] == 'quiz') {
$link = $CFG->wwwroot.'/mod/'.$all_categories[$category][$assignment]['modname'].'/report.php?mode=overview&id='.$link_id->id;
}
else {
$link = $CFG->wwwroot.'/mod/'.$all_categories[$category][$assignment]['modname'].'/view.php?id='.$link_id->id;
}
} else {
$link = $CFG->wwwroot.'/mod/'.$all_categories[$category][$assignment]['modname'].'/view.php?id='.$link_id->id;
}

moodle 1.5.3 student view gradebook fix

The great 1.5.3 gradebook added a bug in the student view of uncategorized grades. The rows for the assignment title and the assignment points possible were each missing a column. This shifted things so it was difficult for students to read. The fix is quick. In grade/lib.php around line 1748 change

else {
$header = '<tr class="header">';
}

to

else {
$header = '<tr class="header"><th rowspan="2">&nbsp;</th>';
}

user activity reporting problems

The user activity reports have a few problems that still need ironed out. My colleague Robert Bill discovered a fix for a problem where a negative time was reported as 1969. In course/user.php change

line 189 from
if (isset($result->time)) {
$timeago = format_time(time() - $result->time);
echo "<td valign=\"top\" nowrap=\"nowrap\">".userdate($result->time)." ($timeago)</td>";
}

to

if (isset($result->time)) {
if ($result->time <= 0) {
$result->time = $instance->timemodified;
}
$timeago = format_time(time() - $result->time);
echo "<td valign=\"top\" nowrap=\"nowrap\">".userdate($result->time)." ($timeago)</td>";
}

picture note 

To avoid any potential trouble with inappropriate pictures in moodle, we added a line right after the picture (271) in user/edit.html that says

<br />Note that <a href="URL to acceptable use policy" target="_new">inappropriate</a> pictures may be deleted by a moodle administrator.

Login as protection

The more I thought about login as, the more I worried it was allowing an instructor to see too much student info inside a course. This discussion was helpful. Note that when an instructor is doing a login as they can only act within their course. With a simple hack you can restrict login as to operate just on a test student account. Instructors can add the test student account to their course and then login as only them. In this example the test student's moodle id is 24. In user/view.php round about line 270 change

if ((isadmin() and !isadmin($user->id)) or (isteacher($course->id) and ($USER->id != $user->id) and !iscreator($user->id))) {

to

if ((isadmin() and !isadmin($user->id)) or (isteacher($course->id) and ($USER->id != $user->id) and ($user->id == '24') and !iscreator($user->id))) {

This just adds the requirement that the user you are looking at has an id of 24. Admins still have full power.

Augsburg moodle plug-ins

augdatabase plug-in

The core of this plug-in is a 3-table setup for enrollment.

  1. augdatabase_dbtable - the main enrollment table like the regular plug-in. There are 2 fields that correspond to the user idnumber and course idnumber fields in moodle.
  2. augdatabase_remoteconverttable - this is a translation table. In our situation, some courses are cross-listed and show up in our registrar data as 2 courses but in reality are a single course. This table will redirect enrollments from the 'child' courses into a combined moodle course. This is different from a metacourse in that the child courses should not exist in moodle.
  3. augdatabase_remoteexcepttable - this is an extra table to handle special 1-off enrollments that don't correspond to our registrar data. This is just as easily done manually in moodle but in the case there were a lot of students this table might be helpful.

As I worked with this more and our user list filled out, it became clear that my choice to tie this to the moodle cron was not going to work. It took way too long (40 minutes) and our enrollment data source was only updated nightly, not live. So I split this plug-in into a new version that has its own command-line php run that can be cronned outside of the moodle cron.php.

Augsburg library

So as I tinkered more I started making my own functions and sprinkling them throughout moodle. I've now collected them into one spot. Download here. Put the folder in your moodle root folder. Most have some instructions in the comments.

There's also 2 scripts in there that can be run from command line php.

03-30-06 :: Addition of new feature, Collect All Posts, for forums
10-14-05 :: Complete rewrite of contact_inactive_students_log to catch students who have never logged in.
09-28-05 :: I was missing a ' in the SQL in contact_inactive_students_log so it really wasn't working!

CourseEval3 RPI Block

We use CourseEval3 for deploying course evaluations. They recently added a "Remote Portal Interface" that feeds a javascript table to other portals. The table contains unfinshed evals for the current user. I wrapped it in a block for moodle users. There is 1 value to change in the block itself (the path to your server's RPI).

Download the 1.5.x block here.

Group-aware course emailer

This is a hacked-up version of the awesome Humboldt Quickmail block. My apologizes to those awesome programmers. You might have to run the SQL to create the table yourself if you try the heavilty customized version. I haven't done a clean install, just upgrades. I had to change the name because we had an existing compose_mail block in courses and I just wanted to replace it. So I changed the name to match. I probably could have updated the block ids in the database but I didn't look into it initially. I did 3 main things:

10-11-05 :: I made a more mainstream version with my tweaks below, this is the one that people should try
10-06-05 :: added feedback when sending email (Sending email to ....).
09-19-05 :: added sorting of groups by name and students by lastname.

Download the heavily customized one here. (go for the other one instead)
Download the mainstream version here. (not yet tested but should be fine!)

Gallery module updated for 1.5

Our faculty really took to the gallery module in 1.4.x so I tweaked it a bit to work better with 1.5. It's framed too so that navigation isn't totally lost.

Download it here.


You might like my blog postings on these things......