/** * Test that modifying a Moodle user also updates the corresponding PM user. */ public function test_modifyingmoodleuserupdatespmuser() { global $CFG, $DB; require_once $CFG->dirroot . '/admin/tool/uploaduser/locallib.php'; $this->load_csv_data(); // Update a record. $src = new stdClass(); $src->id = 100; $src->firstname = 'Testuser'; $src->lastname = 'One'; $src->profile_field_sometext = 'boo'; $src->profile_field_sometextfrompm = 'bla'; $DB->update_record('user', $src); $mdluser = $DB->get_record('user', array('id' => 100)); $mcopy = clone $src; $mcopy = uu_pre_process_custom_profile_data($mcopy); profile_save_data($mcopy); events_trigger('user_updated', $mdluser); // Read the PM user and compare. $retr = new user(103, null, array(), false, array()); $retr->reset_custom_field_list(); $this->assertEquals($mdluser->firstname, $retr->firstname); $this->assertEquals($mdluser->lastname, $retr->lastname); // Check custom fields. $result = new PHPUnit_Extensions_Database_DataSet_DefaultDataSet(); $result->addTable(new moodle_recordset_phpunit_datatable(field_data_int::TABLE, $DB->get_recordset(field_data_int::TABLE, null, '', 'contextid, fieldid, data'))); $result->addTable(new moodle_recordset_phpunit_datatable(field_data_char::TABLE, $DB->get_recordset(field_data_char::TABLE, null, '', 'contextid, fieldid, data'))); $result->addTable(new moodle_recordset_phpunit_datatable(field_data_text::TABLE, $DB->get_recordset(field_data_text::TABLE, null, '', 'contextid, fieldid, data'))); $usercontext = \local_elisprogram\context\user::instance(103); $dataset = new PHPUnit_Extensions_Database_DataSet_CsvDataSet(); $dataset->addTable(field_data_int::TABLE, elispm::file('tests/fixtures/user_field_data_int.csv')); $dataset->addTable(field_data_char::TABLE, elispm::file('tests/fixtures/user_field_data_char.csv')); $dataset->addTable(field_data_text::TABLE, elispm::file('tests/fixtures/user_field_data_text.csv')); $dataset = new PHPUnit_Extensions_Database_DataSet_ReplacementDataSet($dataset); $dataset->addFullReplacement('##USERCTXID##', $usercontext->id); $dataset->addFullReplacement('##USERCTXLVL##', CONTEXT_ELIS_USER); // Only the first text field should be changed; everything else should be the same. $dataset->addFullReplacement('First text entry field', $src->profile_field_sometext); $ret = $dataset->addFullReplacement('Second text entry field', $src->profile_field_sometextfrompm); $this->assertDataSetsEqual($dataset, $result); }
$forcechangepassword = true; } // Use a low cost factor when generating bcrypt hash otherwise // hashing would be slow when uploading lots of users. Hashes // will be automatically updated to a higher cost factor the first // time the user logs in. $user->password = hash_internal_user_password($user->password, true); } } else { $user->password = AUTH_PASSWORD_NOT_CACHED; $upt->track('password', '-', 'normal', false); } $user->id = user_create_user($user, false, false); $upt->track('username', html_writer::link(new moodle_url('/user/profile.php', array('id' => $user->id)), s($user->username)), 'normal', false); // pre-process custom profile menu fields data from csv file $user = uu_pre_process_custom_profile_data($user); // save custom profile fields data profile_save_data($user); if ($forcechangepassword) { set_user_preference('auth_forcepasswordchange', 1, $user); } if ($user->password === 'to be generated') { set_user_preference('create_password', 1, $user); } // Trigger event. \core\event\user_created::create_from_userid($user->id)->trigger(); $upt->track('status', $struseradded); $upt->track('id', $user->id, 'normal', false); $usersnew++; // make sure user context exists context_user::instance($user->id);
/** * Proceed with the import of the user. * * @return void */ public function proceed() { if (!$this->prepared) { throw new coding_exception('The course has not been prepared.'); } else { if ($this->has_errors()) { throw new moodle_exception('Cannot proceed, errors were detected.'); } else { if ($this->processstarted) { throw new coding_exception('The process has already been started.'); } } } $this->processstarted = true; if ($this->do === self::DO_DELETE) { $this->finaldata = $this->existing; try { $success = delete_user($this->existing); } catch (moodle_exception $e) { $success = false; } if (!$success) { $this->error('usernotdeletederror', new lang_string('usernotdeletederror', 'tool_uploadusercli')); return false; } $this->set_status('userdeleted', new lang_string('userdeleted', 'tool_uploaduser')); return true; } else { if ($this->do === self::DO_CREATE) { try { $this->finaldata->id = user_create_user($this->finaldata, false, false); } catch (Exception $e) { $this->error('errorcreatinguser', new lang_string('errorcreatinguser', 'tool_uploadusercli')); return false; } if ($this->needpasswordchange) { set_user_preference('auth_forcepasswordchange', 1, $this->finaldata); $this->set_status('forcepasswordchange', new lang_string('forcepasswordchange', 'tool_uploadusercli')); } if ($this->finaldata->password === 'to be generated') { set_user_preference('create_password', 1, $this->finaldata); } $this->set_status('useradded', new lang_string('newuser')); } else { if ($this->do === self::DO_UPDATE) { try { user_update_user($this->finaldata, false, false); } catch (Exception $e) { $this->error('usernotupdatederror', new lang_string('usernotupdatederror', 'error')); return false; } if ($this->dologout) { \core\session\manager::kill_user_sessions($this->finaldata->id); } $this->set_status('useraccountupdated', new lang_string('useraccountupdated', 'tool_uploaduser')); } } } if ($this->do === self::DO_UPDATE || $this->do === self::DO_CREATE) { if (!$this->isremote) { $this->finaldata = uu_pre_process_custom_profile_data($this->finaldata); profile_save_data($this->finaldata); } $success = $this->add_to_cohort(); $success = $success && $this->add_to_egr(); if (!$success) { return false; } } return true; }
/** * 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; } }
/** * Set up a moodle user. * @param object $mfield The moodle custom field to use. * @param bool $setcountry true to set the Moodle user country field, false to leave it unset * @return object The created moodle user database object. */ protected function set_up_muser($mfield, $setcountry = true) { global $CFG, $DB; require_once $CFG->dirroot . '/admin/tool/uploaduser/locallib.php'; $user = new stdClass(); $user->auth = 'manual'; $user->confirmed = 1; $user->mnethostid = 1; $user->username = '******'; $user->password = md5('12345'); $user->idnumber = 'test_user'; $user->firstname = 'Test'; $user->lastname = 'User'; $user->email = '*****@*****.**'; if ($setcountry) { $user->country = 'CA'; } $profilefieldprop = 'profile_field_' . $mfield->shortname; $user->{$profilefieldprop} = 'onetwothree'; $user->id = $DB->insert_record('user', $user); $user = uu_pre_process_custom_profile_data($user); profile_save_data($user); return $user; }
/** * Update a user * * @param object $record One record of import data * @param string $filename The import file name, used for logging * @return boolean true on success, otherwise false */ function user_update($record, $filename) { global $CFG, $DB; require_once $CFG->dirroot . '/user/lib.php'; require_once $CFG->dirroot . '/user/profile/lib.php'; require_once $CFG->dirroot . '/admin/tool/uploaduser/locallib.php'; //remove invalid fields $record = $this->remove_invalid_user_fields($record); //field length checking $lengthcheck = $this->check_user_field_lengths($record, $filename); if (!$lengthcheck) { return false; } //data checking if (!$this->validate_core_user_data('update', $record, $filename)) { return false; } //profile field validation if (!$this->validate_user_profile_data($record, $filename)) { return false; } // Find existing user record $errors = array(); $error = false; $errsuffix = ''; $uid = $this->get_userid_for_user_actions($record, $filename, $error, $errors, $errsuffix); if ($error) { $this->fslogger->log_failure(implode($errors, ", ") . $errsuffix, 0, $filename, $this->linenumber, $record, "user"); return false; } if ($uid) { $mdluseridnumber = $DB->get_field('user', 'idnumber', array('id' => $uid)); if ($mdluseridnumber != '' && isset($record->idnumber) && $mdluseridnumber != $record->idnumber) { // Attempt to change user's idnumber - not allowed. $identifier = $this->mappings['idnumber']; if ($identifier != 'idnumber') { $identifier = "idnumber ({$identifier})"; } $this->fslogger->log_failure("User's {$identifier} cannot be modified from \"{$mdluseridnumber}\" to \"{$record->idnumber}\".", 0, $filename, $this->linenumber, $record, "user"); return false; } $record->id = $uid; } // See if we should force password change. $requireforcepasswordchange = isset($record->password) && $record->password == 'changeme' ? true : false; // If we require force password change, do not actually change users existing password to "changeme". if ($requireforcepasswordchange) { unset($record->password); } //write to the database //taken from user_update_user // hash the password if (isset($record->password)) { $record->password = hash_internal_user_password($record->password); } $record->timemodified = time(); $DB->update_record('user', $record); $record = uu_pre_process_custom_profile_data($record); profile_save_data($record); // trigger user_updated event on the full database user row $updateduser = $DB->get_record('user', array('id' => $record->id)); events_trigger('user_updated', $updateduser); //string to describe the user $user_descriptor = $this->get_user_descriptor($record); // Set force password change if required. if ($requireforcepasswordchange) { set_user_preference('auth_forcepasswordchange', true, $record->id); } //log success $this->fslogger->log_success("User with {$user_descriptor} successfully updated.", 0, $filename, $this->linenumber); if (!$this->fslogger->get_logfile_status()) { return false; } return true; }