dmlreadexception when running custom mod upgrade in Moodle 2.0 P2

dmlreadexception when running custom mod upgrade in Moodle 2.0 P2

by Basil Gohar -
Number of replies: 3

We have packaged some customizations into our own course module, and everything for install has been working great until just now, when I attempted some further DML modifications. I received a dmlreadexception error when running the following function during our mod's installation:

function eschool_install_assign_capabilities_to_roles()
{
 global $DB;
 //var_dump($DB);
 //exit;

 $roles_capabilities = array(
 'sis_admin' => array(
 // We still need to figure out what an "admin" is in Moodle 2.0
 ),
 'sis_student' => array(
 'mod/eschool:loghours',
 'mod/eschool:canlogin',
 'mod/eschool:viewmymoodlelink',
 'mod/eschool:viewupcomingtestsblock',
 'mod/eschool:synclogintosis'
 ),
 'sis_staff' => array(
 'mod/eschool:canlogin',
 'mod/eschool:forum_canviewpendingposts',
 'mod/eschool:forum_canarchiveanyposts',
 'mod/eschool:forum_canmoderateanyposts',
 'mod/eschool:forum_canpostwithoutmoderation',
 'mod/eschool:migrateuserdata'
 ),
 'sis_director' => array(
 // SIS Director will inherit all the SIS Staff capabilities because they'll also have that role
 ),
 'sis_guardian_system' => array(
 'mod/eschool:viewmymoodlelink', // This should probably be replaced with the "Mentees" block
 'mod/eschool:viewupcomingtestsblock' // Not sure if guardians need to or should see this, but probably
 ),
 'sis_guardian_course' => array(
 // This needs some further examination as it almost certainly will change
 ),
 'sis_guardian_user' => array(
 // This needs some further examination as it almost certainly will change - we need to look at the "Parent" role example on the Moodle wiki
 ),
 'sis_withdrawn_student' => array(
 // The SIS Withdrawn Student role needs the bare minimum to appear in the course for teachers, especially in the gradebook, but to not have access to the course itself
 )
 );

 foreach ($roles_capabilities as $shortname => $capabilities) {
 if (! $role = $DB->get_record('role', array('shortname' => $shortname))) {
 throw new Exception('A role, ' . $shortname . ', was specified which does not exist!');
 }
 $existing_role_capabilities = $DB->get_records('role_capabilities', array('roleid' => $role->id));
 // Remove any capabilities that are not specified above
 foreach ($existing_role_capabilities as $role_capability) {
 if (! in_array($role_capability->capability, $capabilities)) {
 if (! $DB->delete_records('role_capabilities', array('id' => $role_capability->id))) {
 throw new Exception('Unable to delete existing role capabilities for this role!');
 }
 }
 }
 foreach ($capabilities as $capability) {
 $role_capability = new object();
 $role_capability->contextid = '1'; // This looks like the default value from existing examples
 $role_capability->roleid = $role->id;
 $role_capability->capability = $capability;
 $role_capability->permission = '1'; // 1 = "allow"
 $role_capability->timemodified = time();
 $role_capability->modifiedid = '0'; // This looks like the default value from existing examples
 if (! $DB->insert_record('role_capability', $role_capability)) {
 throw new Exception('Unable to insert new role_capability record');
 }
 }
 }

 return true;
}

Can anyone see where a dmlreadexception may be occurring in the above code? What does that mean, exactly? We are using a MySQLi database adapter, by the way.

Please let me know what other information I can provide. Thanks in advance!

Average of ratings: -
In reply to Basil Gohar

Re: dmlreadexception when running custom mod upgrade in Moodle 2.0 P2

by Petr Skoda -
Picture of Core developers Picture of Documentation writers Picture of Peer reviewers Picture of Plugin developers
Hi!

this is not a good approach, because you must not modify roles related tables directly. Please stop doing that in any code, this will break very badly.

Instead use standard db/access.php to do this like the rest of other Moodle plugins. Each new capability gets assigned to specified archetype(legecy) roles automatically. You have to modify custom roles manually via the admin interface after the upgrade/installation.

Petr
In reply to Petr Skoda

Re: dmlreadexception when running custom mod upgrade in Moodle 2.0 P2

by Basil Gohar -
Petr,

Thanks for the reply and the explanation. The only reason we do this is because we run a large number of Moodle instances, each of which will need these modifications. For consistency purposes, we make the upgrades do the database modifications so they are the same across all our clients' machines.

I am afraid that simply assigning the capabilities to archetype roles will not work for us because our new roles don't fit into any of the existing archetypes, and our roles are, in most cases, assigned in the system context.

We've actually been using this same approach without any problems since roles & capabilities were first introduced into Moodle, and we've never had any issues related to it.

Can you offer any other advice, then, on how we can perform this same action, but in a more Moodley way? For example, can the same task be done through, say, a web service? Manually going into the admin screen and creating each role separately is not an acceptable solution for us as we have too many separate instances of Moodle and that approach is likely to be very highly error prone.
In reply to Basil Gohar

Re: dmlreadexception when running custom mod upgrade in Moodle 2.0 P2

by Basil Gohar -
Actually, I found the specific problem I had, which was I had misspelled the access to the role_capabilities table as "role_capability". Not sure why that information wasn't reported in the error message, seems like a mistake that others can make often enough.

However, I'm definitely open to a different, yet automatic, solution to this problem if you have any suggestions.