/** * sync_profile_field_to_moodle function synchronizes ELIS custom user field to corresponding Moodle field if possible. * also syncs relevant field settings * * @param object $field the field object to sync * @return mixed void or true (may throw DB exceptions) * @uses $DB */ function sync_profile_field_to_moodle($field) { global $DB; if (!isset($field->owners['moodle_profile']) || $field->owners['moodle_profile']->exclude == pm_moodle_profile::sync_from_moodle) { // not owned by the Moodle plugin, or set to sync from Moodle return true; } // check if sync is possible with current field settings if (!moodle_profile_can_sync($field->shortname)) { return true; } // Sync field settings first, since they could prevent field data sync sync_profile_field_settings_to_moodle($field); $dest = 'user_info_data'; $src = $field->data_table(); $mfieldid = $DB->get_field('user_info_field', 'id', array('shortname' => $field->shortname)); $joins = 'JOIN {' . user::TABLE . '} cu ON usr.idnumber = cu.idnumber JOIN {context} ctx ON ctx.instanceid = cu.id AND ctx.contextlevel = ' . CONTEXT_ELIS_USER . ' JOIN {' . $src . '} src ON src.contextid = ctx.id AND src.fieldid = ' . $field->id; // insert field values that don't already exist $sql = 'INSERT INTO {' . $dest . '} (userid, fieldid, data) SELECT usr.id AS userid, ' . $mfieldid . ' AS fieldid, src.data FROM {user} usr ' . $joins . ' LEFT JOIN {' . $dest . '} dest ON dest.userid = usr.id AND dest.fieldid = ? WHERE dest.id IS NULL'; $DB->execute($sql, array($mfieldid)); // update already-existing values $sql = 'UPDATE {' . $dest . '} dest JOIN {user} usr ON dest.userid = usr.id ' . $joins . ' SET dest.data = src.data WHERE dest.fieldid = ?'; $DB->execute($sql, array($mfieldid)); }
/** * Function to synchronize the curriculum data with the Moodle data. * * @param boolean $tomoodle Optional direction to synchronize the data. * @param boolean $strict_match Whether we should use the association table rather * than just check idnumbers when comparing to Moodle users * */ function synchronize_moodle_user($tomoodle = true, $createnew = false, $strict_match = true) { global $CFG; require_once $CFG->dirroot . '/admin/tool/uploaduser/locallib.php'; require_once elispm::lib('data/usermoodle.class.php'); require_once elis::lib('lib.php'); static $mu_loop_detect = array(); // Create a new Moodle user record to update with. if (!($muser = $this->get_moodleuser($strict_match)) && !$createnew) { return false; } $muserid = $muser ? $muser->id : false; if ($tomoodle) { // map PM user fields to Moodle user fields $mdlfieldmap = array('idnumber' => 'idnumber', 'username' => 'username', 'firstname' => 'firstname', 'lastname' => 'lastname', 'email' => 'email', 'address' => 'address', 'city' => 'city', 'country' => 'country', 'language' => 'lang'); // determine if the user is already noted as having been associated to a PM user if ($um = usermoodle::find(new field_filter('cuserid', $this->id))) { if ($um->valid()) { $um = $um->current(); // determine if the PM user idnumber was updated if ($um->idnumber != $this->idnumber) { // update the Moodle user with the new idnumber $muser = new stdClass(); $muser->id = $um->muserid; $muser->idnumber = $this->idnumber; $this->_db->update_record('user', $muser); // update the association table with the new idnumber $um->idnumber = $this->idnumber; $um->save(); } } } //try to update the idnumber of a matching Moodle user that //doesn't have an idnumber set yet $exists_params = array('username' => $this->username, 'mnethostid' => $CFG->mnet_localhost_id); if ($moodle_user = $this->_db->get_record('user', $exists_params)) { if (empty($moodle_user->idnumber)) { //potentially old data, so set the idnumber $moodle_user->idnumber = $this->idnumber; $this->_db->update_record('user', $moodle_user); $muserid = $moodle_user->id; } else { if ($this->idnumber != $moodle_user->idnumber) { //the username points to a pre-existing Moodle user //with a non-matching idnumber, so something horrible //happened return; } } } if ($createnew && !$muserid) { /// Add a new user $record = new stdClass(); foreach ($mdlfieldmap as $pmfield => $mdlfield) { if (isset($this->{$pmfield})) { $record->{$mdlfield} = $this->{$pmfield}; } } $record->password = $this->password === null ? '' : $this->password; $record->confirmed = 1; $record->mnethostid = $CFG->mnet_localhost_id; $record->timemodified = time(); $record->id = $this->_db->insert_record('user', $record); } else { if ($muserid) { /// Update an existing user $record = new stdClass(); $record->id = $muserid; foreach ($mdlfieldmap as $pmfield => $mdlfield) { if (isset($this->{$pmfield})) { $record->{$mdlfield} = $this->{$pmfield}; } } if (!empty($this->password)) { $record->password = $this->password; } $record->timemodified = time(); $this->_db->update_record('user', $record); } else { return true; } } // avoid update loops if (isset($mu_loop_detect[$this->id])) { return $record->id; } $mu_loop_detect[$this->id] = true; // synchronize profile fields $origrec = clone $record; profile_load_data($origrec); fix_moodle_profile_fields($origrec); $fields = field::get_for_context_level(CONTEXT_ELIS_USER); $mfields = $this->_db->get_records('user_info_field', array(), '', 'shortname'); $fields = $fields ? $fields : array(); $changed = false; require_once elis::plugin_file('elisfields_moodleprofile', 'custom_fields.php'); foreach ($fields as $field) { $field = new field($field); if (!moodle_profile_can_sync($field->shortname)) { continue; } if (isset($field->owners['moodle_profile']) && $field->owners['moodle_profile']->exclude == pm_moodle_profile::sync_to_moodle && isset($mfields[$field->shortname])) { $shortname = $field->shortname; $fieldname = "field_{$shortname}"; $mfieldname = "profile_{$fieldname}"; $mfieldvalue = isset($origrec->{$mfieldname}) ? $origrec->{$mfieldname} : null; if ($mfieldvalue != $this->{$fieldname}) { $record->{$mfieldname} = $this->{$fieldname}; $changed = true; sync_profile_field_settings_to_moodle($field); } } } $record = uu_pre_process_custom_profile_data($record); profile_save_data($record); if ($muserid) { if ($changed) { events_trigger('user_updated', $record); } } else { // if no user association record exists, create one $um = new usermoodle(); $um->cuserid = $this->id; $um->muserid = $record->id; $um->idnumber = $this->idnumber; $um->save(); events_trigger('user_created', $record); } unset($mu_loop_detect[$this->id]); return $record->id; } }
/** * Validate that Moodle & ELIS custom user field settings are synced. * @param array $moodlefielddata Array of moodle field params * @param array $elisfielddata Array of elis field, context & owner params * @param bool $cansync True if Moodle & ELIS field should be sync-able * @param array $moodlefieldexpect Array of expected Moodle field values * @param array $elisfieldexpect Array of expected ELIS field/owner values * @uses $DB * @dataProvider customfieldsync_dataprovider */ public function test_custom_user_field_settings_synced($moodlefielddata, $elisfielddata, $cansync, $moodlefieldexpect, $elisfieldexpect) { global $DB; // Create Moodle profile field with data. if (!empty($moodlefielddata)) { $DB->insert_record('user_info_field', (object) $moodlefielddata); } // Create ELIS field, context & owner data. $field = $this->build_elis_field_data($elisfielddata); $this->assertTrue(moodle_profile_can_sync($field->shortname) == $cansync); sync_profile_field_settings_to_moodle($field); sync_profile_field_settings_from_moodle($field); if (!empty($moodlefieldexpect)) { $mdlfield = $DB->get_record('user_info_field', array('shortname' => $field->shortname)); foreach ($moodlefieldexpect as $key => $val) { $this->assertEquals($val, $mdlfield->{$key}); } } $this->assert_elis_field_data($field, $elisfieldexpect); }