Merge commit 'catalyst/MOODLE_19_STABLE' into mdl19-linuxchix
[moodle-linuxchix.git] / enrol / database / enrol.php
blob31636b61b3286b7a4930638ad84c38d10f7fa80f
1 <?php // $Id$
3 require_once($CFG->dirroot.'/enrol/enrol.class.php');
5 class enrolment_plugin_database {
7 var $log;
9 /*
10 * For the given user, let's go out and look in an external database
11 * for an authoritative list of enrolments, and then adjust the
12 * local Moodle assignments to match.
14 function setup_enrolments(&$user) {
15 global $CFG;
17 // NOTE: if $this->enrol_connect() succeeds you MUST remember to call
18 // $this->enrol_disconnect() as it is doing some nasty vodoo with $CFG->prefix
19 $enroldb = $this->enrol_connect();
20 if (!$enroldb) {
21 error_log('[ENROL_DB] Could not make a connection');
22 return;
25 // If we are expecting to get role information from our remote db, then
26 // we execute the below code for every role type. Otherwise we just
27 // execute it once with null (hence the dummy array).
28 $roles = !empty($CFG->enrol_db_remoterolefield) && !empty($CFG->enrol_db_localrolefield)
29 ? get_records('role')
30 : array(null);
32 //error_log('[ENROL_DB] found ' . count($roles) . ' roles:');
34 foreach($roles as $role) {
36 //error_log('[ENROL_DB] setting up enrolments for '.$role->shortname);
38 /// Get the authoritative list of enrolments from the external database table
39 /// We're using the ADOdb functions natively here and not our datalib functions
40 /// because we didn't want to mess with the $db global
42 $useridfield = $enroldb->quote($user->{$CFG->enrol_localuserfield});
44 list($have_role, $remote_role_name, $remote_role_value) = $this->role_fields($enroldb, $role);
46 /// Check if a particular role has been forced by the plugin site-wide
47 /// (if we aren't doing a role-based select)
48 if (!$have_role && $CFG->enrol_db_defaultcourseroleid) {
49 $role = get_record('role', 'id', $CFG->enrol_db_defaultcourseroleid);
52 /// Whether to fetch the default role on a per-course basis (below) or not.
53 $use_default_role = !$role;
56 if ($have_role) {
57 error_log('[ENROL_DB] Doing role-specific select from db for role: '.$role->shortname);
58 } elseif ($use_default_role) {
59 error_log('[ENROL_DB] Using course default for roles - assuming that database lists defaults');
60 } else {
61 error_log('[ENROL_DB] Using config default for roles: '.$role->shortname);
62 }*/
64 if ($rs = $enroldb->Execute("SELECT {$CFG->enrol_remotecoursefield} as enrolremotecoursefield
65 FROM {$CFG->enrol_dbtable}
66 WHERE {$CFG->enrol_remoteuserfield} = " . $useridfield .
67 (isset($remote_role_name, $remote_role_value) ? ' AND '.$remote_role_name.' = '.$remote_role_value : ''))) {
69 // We'll use this to see what to add and remove
70 $existing = $role
71 ? get_records_sql("
72 SELECT * FROM {$CFG->prefix}role_assignments
73 WHERE userid = {$user->id}
74 AND roleid = {$role->id}")
75 : get_records('role_assignments', 'userid', $user->id);
77 if (!$existing) {
78 $existing = array();
82 if (!$rs->EOF) { // We found some courses
84 //$count = 0;
85 $courselist = array();
86 while ($fields_obj = rs_fetch_next_record($rs)) { // Make a nice little array of courses to process
87 $fields_obj = (object)array_change_key_case((array)$fields_obj , CASE_LOWER);
88 $courselist[] = $fields_obj->enrolremotecoursefield;
89 //$count++;
91 rs_close($rs);
93 //error_log('[ENROL_DB] Found '.count($existing).' existing roles and '.$count.' in external database');
95 foreach ($courselist as $coursefield) { /// Check the list of courses against existing
96 $course = get_record('course', $CFG->enrol_localcoursefield, $coursefield);
97 if (!is_object($course)) {
98 if (empty($CFG->enrol_db_autocreate)) { // autocreation not allowed
99 if (debugging('',DEBUG_ALL)) {
100 error_log( "Course $coursefield does not exist, skipping") ;
102 continue; // next foreach course
104 // ok, now then let's create it!
105 // prepare any course properties we actually have
106 $course = new StdClass;
107 $course->{$CFG->enrol_localcoursefield} = $coursefield;
108 $course->fullname = $coursefield;
109 $course->shortname = $coursefield;
110 if (!($newcourseid = $this->create_course($course, true)
111 and $course = get_record( 'course', 'id', $newcourseid))) {
112 error_log( "Creating course $coursefield failed");
113 continue; // nothing left to do...
117 // if the course is hidden and we don't want to enrol in hidden courses
118 // then just skip it
119 if (!$course->visible and $CFG->enrol_db_ignorehiddencourse) {
120 continue;
123 /// If there's no role specified, we get the default course role (usually student)
124 if ($use_default_role) {
125 $role = get_default_course_role($course);
128 $context = get_context_instance(CONTEXT_COURSE, $course->id);
130 // Couldn't get a role or context, skip.
131 if (!$role || !$context) {
132 continue;
135 // Search the role assignments to see if this user
136 // already has this role in this context. If it is, we
137 // skip to the next course.
138 foreach($existing as $key => $role_assignment) {
139 if ($role_assignment->roleid == $role->id
140 && $role_assignment->contextid == $context->id) {
141 unset($existing[$key]);
142 //error_log('[ENROL_DB] User is already enroled in course '.$course->idnumber);
143 continue 2;
147 //error_log('[ENROL_DB] Enrolling user in course '.$course->idnumber);
148 role_assign($role->id, $user->id, 0, $context->id, 0, 0, 0, 'database');
150 } // We've processed all external courses found
152 /// We have some courses left that we might need to unenrol from
153 /// Note: we only process enrolments that we (ie 'database' plugin) made
154 /// Do not unenrol anybody if the disableunenrol option is 'yes'
155 if (!$CFG->enrol_db_disableunenrol) {
156 foreach ($existing as $role_assignment) {
157 if ($role_assignment->enrol == 'database') {
158 //error_log('[ENROL_DB] Removing user from context '.$role_assignment->contextid);
159 role_unassign($role_assignment->roleid, $user->id, '', $role_assignment->contextid);
163 } else {
164 error_log('[ENROL_DB] Couldn\'t get rows from external db: '.$enroldb->ErrorMsg());
167 $this->enrol_disconnect($enroldb);
171 * sync enrolments with database, create courses if required.
173 * @param object The role to sync for. If no role is specified, defaults are
174 * used.
176 function sync_enrolments($role = null) {
177 global $CFG;
178 global $db;
179 error_reporting(E_ALL);
181 // Connect to the external database
182 $enroldb = $this->enrol_connect();
183 if (!$enroldb) {
184 notify("enrol/database cannot connect to server");
185 return false;
188 if (isset($role)) {
189 echo '=== Syncing enrolments for role: '.$role->shortname." ===\n";
190 } else {
191 echo "=== Syncing enrolments for default role ===\n";
194 // first, pack the sortorder...
195 fix_course_sortorder();
197 list($have_role, $remote_role_name, $remote_role_value) = $this->role_fields($enroldb, $role);
199 if (!$have_role) {
200 if (!empty($CFG->enrol_db_defaultcourseroleid)
201 and $role = get_record('role', 'id', $CFG->enrol_db_defaultcourseroleid)) {
202 echo "=== Using enrol_db_defaultcourseroleid: {$role->id} ({$role->shortname}) ===\n";
203 } elseif (isset($role)) {
204 echo "!!! WARNING: Role specified by caller, but no (or invalid) role configuration !!!\n";
208 // get enrolments per-course
209 $sql = "SELECT DISTINCT {$CFG->enrol_remotecoursefield} " .
210 " FROM {$CFG->enrol_dbtable} " .
211 " WHERE {$CFG->enrol_remoteuserfield} IS NOT NULL" .
212 (isset($remote_role_name, $remote_role_value) ? ' AND '.$remote_role_name.' = '.$remote_role_value : '');
214 $rs = $enroldb->Execute($sql);
215 if (!$rs) {
216 trigger_error($enroldb->ErrorMsg() .' STATEMENT: '. $sql);
217 return false;
219 if ( $rs->EOF ) { // no courses! outta here...
220 return true;
223 begin_sql();
224 $extcourses = array();
225 while ($extcourse_obj = rs_fetch_next_record($rs)) { // there are more course records
226 $extcourse_obj = (object)array_change_key_case((array)$extcourse_obj , CASE_LOWER);
227 $extcourse = $extcourse_obj->{strtolower($CFG->enrol_remotecoursefield)};
228 array_push($extcourses, $extcourse);
230 // does the course exist in moodle already?
231 $course = false;
232 $course = get_record( 'course',
233 $CFG->enrol_localcoursefield,
234 $extcourse );
236 if (!is_object($course)) {
237 if (empty($CFG->enrol_db_autocreate)) { // autocreation not allowed
238 if (debugging('', DEBUG_ALL)) {
239 error_log( "Course $extcourse does not exist, skipping");
241 continue; // next foreach course
243 // ok, now then let's create it!
244 // prepare any course properties we actually have
245 $course = new StdClass;
246 $course->{$CFG->enrol_localcoursefield} = $extcourse;
247 $course->fullname = $extcourse;
248 $course->shortname = $extcourse;
249 if (!($newcourseid = $this->create_course($course, true)
250 and $course = get_record( 'course', 'id', $newcourseid))) {
251 error_log( "Creating course $extcourse failed");
252 continue; // nothing left to do...
257 $context = get_context_instance(CONTEXT_COURSE, $course->id);
259 // If we don't have a proper role setup, then we default to the default
260 // role for the current course.
261 if (!$have_role) {
262 $role = get_default_course_role($course);
265 // get a list of the student ids the are enrolled
266 // in the external db -- hopefully it'll fit in memory...
267 $extenrolments = array();
268 $sql = "SELECT {$CFG->enrol_remoteuserfield} " .
269 " FROM {$CFG->enrol_dbtable} " .
270 " WHERE {$CFG->enrol_remotecoursefield} = " . $enroldb->quote($extcourse) .
271 ($have_role ? ' AND '.$remote_role_name.' = '.$remote_role_value : '');
273 $crs = $enroldb->Execute($sql);
274 if (!$crs) {
275 trigger_error($enroldb->ErrorMsg() .' STATEMENT: '. $sql);
276 return false;
278 if ( $crs->EOF ) { // shouldn't happen, but cover all bases
279 continue;
282 // slurp results into an array
283 while ($crs_obj = rs_fetch_next_record($crs)) {
284 $crs_obj = (object)array_change_key_case((array)$crs_obj , CASE_LOWER);
285 array_push($extenrolments, $crs_obj->{strtolower($CFG->enrol_remoteuserfield)});
287 rs_close($crs); // release the handle
290 // prune enrolments to users that are no longer in ext auth
291 // hopefully they'll fit in the max buffer size for the RDBMS
293 // TODO: This doesn't work perfectly. If we are operating without
294 // roles in the external DB, then this doesn't handle changes of role
295 // within a course (because the user is still enrolled in the course,
296 // so NOT IN misses the course).
298 // When the user logs in though, their role list will be updated
299 // correctly.
301 if (!$CFG->enrol_db_disableunenrol) {
302 $to_prune = get_records_sql("
303 SELECT ra.*
304 FROM {$CFG->prefix}role_assignments ra
305 JOIN {$CFG->prefix}user u ON ra.userid = u.id
306 WHERE ra.enrol = 'database'
307 AND ra.contextid = {$context->id}
308 AND ra.roleid = ". $role->id . ($extenrolments
309 ? " AND u.{$CFG->enrol_localuserfield} NOT IN (".join(", ", array_map(array(&$db, 'quote'), $extenrolments)).")"
310 : ''));
312 if ($to_prune) {
313 foreach ($to_prune as $role_assignment) {
314 if (role_unassign($role->id, $role_assignment->userid, 0, $role_assignment->contextid)){
315 error_log( "Unassigned {$role->shortname} assignment #{$role_assignment->id} for course {$course->id} (" . format_string($course->shortname) . "); user {$role_assignment->userid}");
316 } else {
317 error_log( "Failed to unassign {$role->shortname} assignment #{$role_assignment->id} for course {$course->id} (" . format_string($course->shortname) . "); user {$role_assignment->userid}");
324 // insert current enrolments
325 // bad we can't do INSERT IGNORE with postgres...
327 foreach ($extenrolments as $member) {
328 // Get the user id and whether is enrolled in one fell swoop
329 $sql = "
330 SELECT u.id AS userid, ra.id AS enrolmentid
331 FROM {$CFG->prefix}user u
332 LEFT OUTER JOIN {$CFG->prefix}role_assignments ra ON u.id = ra.userid
333 AND ra.roleid = {$role->id}
334 AND ra.contextid = {$context->id}
335 WHERE u.{$CFG->enrol_localuserfield} = ".$db->quote($member) .
336 " AND (u.deleted IS NULL OR u.deleted=0) ";
338 $ers = $db->Execute($sql);
339 if (!$ers) {
340 trigger_error($db->ErrorMsg() .' STATEMENT: '. $sql);
341 return false;
343 if ( $ers->EOF ) { // if this returns empty, it means we don't have the student record.
344 // should not happen -- but skip it anyway
345 trigger_error('weird! no user record entry?');
346 continue;
348 $user_obj = rs_fetch_record($ers);
349 $userid = $user_obj->userid;
350 $enrolmentid = $user_obj->enrolmentid;
351 rs_close($ers); // release the handle
353 if ($enrolmentid) { // already enrolled - skip
354 continue;
357 if (role_assign($role->id, $userid, 0, $context->id, 0, 0, 0, 'database')){
358 error_log( "Assigned role {$role->shortname} to user {$userid} in course {$course->id} (" . format_string($course->shortname) . ")");
359 } else {
360 error_log( "Failed to assign role {$role->shortname} to user {$userid} in course {$course->id} (" . format_string($course->shortname) . ")");
363 } // end foreach member
364 } // end while course records
365 rs_close($rs); //Close the main course recordset
368 // prune enrolments to courses that are no longer in ext auth
370 // TODO: This doesn't work perfectly. If we are operating without
371 // roles in the external DB, then this doesn't handle changes of role
372 // within a course (because the user is still enrolled in the course,
373 // so NOT IN misses the course).
375 // When the user logs in though, their role list will be updated
376 // correctly.
378 if (!$CFG->enrol_db_disableunenrol) {
379 $sql = "
380 SELECT ra.roleid, ra.userid, ra.contextid
381 FROM {$CFG->prefix}role_assignments ra
382 JOIN {$CFG->prefix}context cn ON cn.id = ra.contextid
383 JOIN {$CFG->prefix}course c ON c.id = cn.instanceid
384 WHERE ra.enrol = 'database'
385 AND cn.contextlevel = ".CONTEXT_COURSE." " .
386 ($have_role ? ' AND ra.roleid = '.$role->id : '') .
387 ($extcourses
388 ? " AND c.{$CFG->enrol_localcoursefield} NOT IN (" . join(",", array_map(array(&$db, 'quote'), $extcourses)) . ")"
389 : '');
391 $ers = $db->Execute($sql);
392 if (!$ers) {
393 trigger_error($db->ErrorMsg() .' STATEMENT: '. $sql);
394 return false;
396 if ( !$ers->EOF ) {
397 while ($user_obj = rs_fetch_next_record($ers)) {
398 $user_obj = (object)array_change_key_case((array)$user_obj , CASE_LOWER);
399 $roleid = $user_obj->roleid;
400 $user = $user_obj->userid;
401 $contextid = $user_obj->contextid;
402 if (role_unassign($roleid, $user, 0, $contextid)){
403 error_log( "Unassigned role {$roleid} from user $user in context $contextid");
404 } else {
405 error_log( "Failed unassign role {$roleid} from user $user in context $contextid");
408 rs_close($ers); // release the handle
412 commit_sql();
414 // we are done now, a bit of housekeeping
415 fix_course_sortorder();
417 $this->enrol_disconnect($enroldb);
418 return true;
421 /// Overide the get_access_icons() function
422 function get_access_icons($course) {
426 /// Overide the base config_form() function
427 function config_form($frm) {
428 global $CFG;
430 $vars = array('enrol_dbhost', 'enrol_dbuser', 'enrol_dbpass',
431 'enrol_dbname', 'enrol_dbtable',
432 'enrol_localcoursefield', 'enrol_localuserfield',
433 'enrol_remotecoursefield', 'enrol_remoteuserfield',
434 'enrol_db_autocreate', 'enrol_db_category', 'enrol_db_template',
435 'enrol_db_localrolefield', 'enrol_db_remoterolefield',
436 'enrol_remotecoursefield', 'enrol_remoteuserfield',
437 'enrol_db_ignorehiddencourse', 'enrol_db_defaultcourseroleid',
438 'enrol_db_disableunenrol');
440 foreach ($vars as $var) {
441 if (!isset($frm->$var)) {
442 $frm->$var = '';
445 include("$CFG->dirroot/enrol/database/config.html");
448 /// Override the base process_config() function
449 function process_config($config) {
451 if (!isset($config->enrol_dbtype)) {
452 $config->enrol_dbtype = 'mysql';
454 set_config('enrol_dbtype', $config->enrol_dbtype);
456 if (!isset($config->enrol_dbhost)) {
457 $config->enrol_dbhost = '';
459 set_config('enrol_dbhost', $config->enrol_dbhost);
461 if (!isset($config->enrol_dbuser)) {
462 $config->enrol_dbuser = '';
464 set_config('enrol_dbuser', $config->enrol_dbuser);
466 if (!isset($config->enrol_dbpass)) {
467 $config->enrol_dbpass = '';
469 set_config('enrol_dbpass', $config->enrol_dbpass);
471 if (!isset($config->enrol_dbname)) {
472 $config->enrol_dbname = '';
474 set_config('enrol_dbname', $config->enrol_dbname);
476 if (!isset($config->enrol_dbtable)) {
477 $config->enrol_dbtable = '';
479 set_config('enrol_dbtable', $config->enrol_dbtable);
481 if (!isset($config->enrol_localcoursefield)) {
482 $config->enrol_localcoursefield = '';
484 set_config('enrol_localcoursefield', $config->enrol_localcoursefield);
486 if (!isset($config->enrol_localuserfield)) {
487 $config->enrol_localuserfield = '';
489 set_config('enrol_localuserfield', $config->enrol_localuserfield);
491 if (!isset($config->enrol_remotecoursefield)) {
492 $config->enrol_remotecoursefield = '';
494 set_config('enrol_remotecoursefield', $config->enrol_remotecoursefield);
496 if (!isset($config->enrol_remoteuserfield)) {
497 $config->enrol_remoteuserfield = '';
499 set_config('enrol_remoteuserfield', $config->enrol_remoteuserfield);
501 if (!isset($config->enrol_db_autocreate)) {
502 $config->enrol_db_autocreate = '';
504 set_config('enrol_db_autocreate', $config->enrol_db_autocreate);
506 if (!isset($config->enrol_db_category)) {
507 $config->enrol_db_category = '';
509 set_config('enrol_db_category', $config->enrol_db_category);
511 if (!isset($config->enrol_db_template)) {
512 $config->enrol_db_template = '';
514 set_config('enrol_db_template', $config->enrol_db_template);
516 if (!isset($config->enrol_db_defaultcourseroleid)) {
517 $config->enrol_db_defaultcourseroleid = '';
519 set_config('enrol_db_defaultcourseroleid', $config->enrol_db_defaultcourseroleid);
521 if (!isset($config->enrol_db_localrolefield)) {
522 $config->enrol_db_localrolefield = '';
524 set_config('enrol_db_localrolefield', $config->enrol_db_localrolefield);
526 if (!isset($config->enrol_db_remoterolefield)) {
527 $config->enrol_db_remoterolefield = '';
529 set_config('enrol_db_remoterolefield', $config->enrol_db_remoterolefield);
531 if (!isset($config->enrol_db_ignorehiddencourse)) {
532 $config->enrol_db_ignorehiddencourse = '';
534 set_config('enrol_db_ignorehiddencourse', $config->enrol_db_ignorehiddencourse );
536 if (!isset($config->enrol_db_disableunenrol)) {
537 $config->enrol_db_disableunenrol = '';
539 set_config('enrol_db_disableunenrol', $config->enrol_db_disableunenrol );
541 return true;
544 // will create the moodle course from the template
545 // course_ext is an array as obtained from ldap -- flattened somewhat
546 // NOTE: if you pass true for $skip_fix_course_sortorder
547 // you will want to call fix_course_sortorder() after your are done
548 // with course creation
549 function create_course ($course,$skip_fix_course_sortorder=0){
550 global $CFG;
552 // define a template
553 if(!empty($CFG->enrol_db_template)){
554 $template = get_record("course", 'shortname', $CFG->enrol_db_template);
555 $template = (array)$template;
556 } else {
557 $site = get_site();
558 $template = array(
559 'startdate' => time() + 3600 * 24,
560 'summary' => get_string("defaultcoursesummary"),
561 'format' => "weeks",
562 'password' => "",
563 'guest' => 0,
564 'numsections' => 10,
565 'idnumber' => '',
566 'cost' => '',
567 'newsitems' => 5,
568 'showgrades' => 1,
569 'groupmode' => 0,
570 'groupmodeforce' => 0,
571 'student' => $site->student,
572 'students' => $site->students,
573 'teacher' => $site->teacher,
574 'teachers' => $site->teachers,
577 // overlay template
578 foreach (array_keys($template) AS $key) {
579 if (empty($course->$key)) {
580 $course->$key = $template[$key];
584 $course->category = 1; // the misc 'catch-all' category
585 if (!empty($CFG->enrol_db_category)){ //category = 0 or undef will break moodle
586 $course->category = $CFG->enrol_db_category;
589 // define the sortorder
590 $sort = get_field_sql('SELECT COALESCE(MAX(sortorder)+1, 100) AS max ' .
591 ' FROM ' . $CFG->prefix . 'course ' .
592 ' WHERE category=' . $course->category);
593 $course->sortorder = $sort;
595 // override with local data
596 $course->startdate = time() + 3600 * 24;
597 $course->timecreated = time();
598 $course->visible = 1;
600 // clear out id just in case
601 unset($course->id);
603 // truncate a few key fields
604 $course->idnumber = substr($course->idnumber, 0, 100);
605 $course->shortname = substr($course->shortname, 0, 100);
607 // store it and log
608 if ($newcourseid = insert_record("course", addslashes_object($course))) { // Set up new course
609 $section = NULL;
610 $section->course = $newcourseid; // Create a default section.
611 $section->section = 0;
612 $section->id = insert_record("course_sections", $section);
613 $page = page_create_object(PAGE_COURSE_VIEW, $newcourseid);
614 blocks_repopulate_page($page); // Return value no
617 if(!$skip_fix_course_sortorder){
618 fix_course_sortorder();
620 add_to_log($newcourseid, "course", "new", "view.php?id=$newcourseid", "enrol/database auto-creation");
621 } else {
622 trigger_error("Could not create new course $extcourse from from database");
623 notify("Serious Error! Could not create the new course!");
624 return false;
627 return $newcourseid;
630 /// DB Connect
631 /// NOTE: You MUST remember to disconnect
632 /// when you stop using it -- as this call will
633 /// sometimes modify $CFG->prefix for the whole of Moodle!
634 function enrol_connect() {
635 global $CFG;
637 // Try to connect to the external database (forcing new connection)
638 $enroldb = &ADONewConnection($CFG->enrol_dbtype);
639 if ($enroldb->Connect($CFG->enrol_dbhost, $CFG->enrol_dbuser, $CFG->enrol_dbpass, $CFG->enrol_dbname, true)) {
640 $enroldb->SetFetchMode(ADODB_FETCH_ASSOC); ///Set Assoc mode always after DB connection
641 return $enroldb;
642 } else {
643 trigger_error("Error connecting to enrolment DB backend with: "
644 . "$CFG->enrol_dbhost,$CFG->enrol_dbuser,$CFG->enrol_dbpass,$CFG->enrol_dbname");
645 return false;
649 /// DB Disconnect
650 function enrol_disconnect($enroldb) {
651 global $CFG;
653 $enroldb->Close();
657 * This function returns the name and value of the role field to query the db
658 * for, or null if there isn't one.
660 * @param object The ADOdb connection
661 * @param object The role
662 * @return array (boolean, string, db quoted string)
664 function role_fields($enroldb, $role) {
665 global $CFG;
667 if ($have_role = !empty($role)
668 && !empty($CFG->enrol_db_remoterolefield)
669 && !empty($CFG->enrol_db_localrolefield)
670 && !empty($role->{$CFG->enrol_db_localrolefield})) {
671 $remote_role_name = $CFG->enrol_db_remoterolefield;
672 $remote_role_value = $enroldb->quote($role->{$CFG->enrol_db_localrolefield});
673 } else {
674 $remote_role_name = $remote_role_value = null;
677 return array($have_role, $remote_role_name, $remote_role_value);
680 } // end of class