mirror of
https://github.com/moodle/moodle.git
synced 2025-06-02 22:25:04 +02:00
MDL-40613 auth_ldap: sync custom profile fields
This commit is contained in:
parent
95b7be7f05
commit
2c977ceb29
@ -545,67 +545,6 @@ class auth_plugin_db extends auth_plugin_base {
|
||||
return $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* will update a local user record from an external source.
|
||||
* is a lighter version of the one in moodlelib -- won't do
|
||||
* expensive ops such as enrolment.
|
||||
*
|
||||
* If you don't pass $updatekeys, there is a performance hit and
|
||||
* values removed from DB won't be removed from moodle.
|
||||
*
|
||||
* @param string $username username
|
||||
* @param bool $updatekeys
|
||||
* @return stdClass
|
||||
*/
|
||||
function update_user_record($username, $updatekeys=false) {
|
||||
global $CFG, $DB;
|
||||
|
||||
//just in case check text case
|
||||
$username = trim(core_text::strtolower($username));
|
||||
|
||||
// get the current user record
|
||||
$user = $DB->get_record('user', array('username'=>$username, 'mnethostid'=>$CFG->mnet_localhost_id));
|
||||
if (empty($user)) { // trouble
|
||||
error_log("Cannot update non-existent user: $username");
|
||||
print_error('auth_dbusernotexist','auth_db',$username);
|
||||
die;
|
||||
}
|
||||
|
||||
// Ensure userid is not overwritten.
|
||||
$userid = $user->id;
|
||||
$needsupdate = false;
|
||||
|
||||
$updateuser = new stdClass();
|
||||
$updateuser->id = $userid;
|
||||
if ($newinfo = $this->get_userinfo($username)) {
|
||||
$newinfo = truncate_userinfo($newinfo);
|
||||
|
||||
if (empty($updatekeys)) { // All keys? This does not support removing values.
|
||||
$updatekeys = array_keys($newinfo);
|
||||
}
|
||||
|
||||
foreach ($updatekeys as $key) {
|
||||
if (isset($newinfo[$key])) {
|
||||
$value = $newinfo[$key];
|
||||
} else {
|
||||
$value = '';
|
||||
}
|
||||
|
||||
if (!empty($this->config->{'field_updatelocal_' . $key})) {
|
||||
if (isset($user->{$key}) and $user->{$key} != $value) { // Only update if it's changed.
|
||||
$needsupdate = true;
|
||||
$updateuser->$key = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($needsupdate) {
|
||||
require_once($CFG->dirroot . '/user/lib.php');
|
||||
user_update_user($updateuser);
|
||||
}
|
||||
return $DB->get_record('user', array('id'=>$userid, 'deleted'=>0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the user record is updated.
|
||||
* Modifies user in external database. It takes olduser (before changes) and newuser (after changes)
|
||||
|
@ -928,14 +928,24 @@ class auth_plugin_ldap extends auth_plugin_base {
|
||||
|
||||
$id = user_create_user($user, false);
|
||||
echo "\t"; print_string('auth_dbinsertuser', 'auth_db', array('name'=>$user->username, 'id'=>$id)); echo "\n";
|
||||
$user = $DB->get_record('user', array('id' => $id));
|
||||
$euser = $DB->get_record('user', array('id' => $id));
|
||||
|
||||
if (!empty($this->config->forcechangepassword)) {
|
||||
set_user_preference('auth_forcepasswordchange', 1, $id);
|
||||
}
|
||||
|
||||
// Save custom profile fields.
|
||||
$euser->profile = array();
|
||||
foreach ($user as $key => $value) {
|
||||
if (preg_match('/^profile_field_(.*)$/', $key, $match)) {
|
||||
$field = $match[1];
|
||||
$euser->profile[$field] = $user->$key;
|
||||
}
|
||||
}
|
||||
profile_save_custom_fields($euser);
|
||||
|
||||
// Add roles if needed.
|
||||
$this->sync_roles($user);
|
||||
$this->sync_roles($euser);
|
||||
|
||||
}
|
||||
$transaction->allow_commit();
|
||||
@ -950,72 +960,6 @@ class auth_plugin_ldap extends auth_plugin_base {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a local user record from an external source.
|
||||
* This is a lighter version of the one in moodlelib -- won't do
|
||||
* expensive ops such as enrolment.
|
||||
*
|
||||
* If you don't pass $updatekeys, there is a performance hit and
|
||||
* values removed from LDAP won't be removed from moodle.
|
||||
*
|
||||
* @param string $username username
|
||||
* @param boolean $updatekeys true to update the local record with the external LDAP values.
|
||||
* @param bool $triggerevent set false if user_updated event should not be triggered.
|
||||
* This will not affect user_password_updated event triggering.
|
||||
* @return stdClass|bool updated user record or false if there is no new info to update.
|
||||
*/
|
||||
function update_user_record($username, $updatekeys = false, $triggerevent = false) {
|
||||
global $CFG, $DB;
|
||||
|
||||
// Just in case check text case
|
||||
$username = trim(core_text::strtolower($username));
|
||||
|
||||
// Get the current user record
|
||||
$user = $DB->get_record('user', array('username'=>$username, 'mnethostid'=>$CFG->mnet_localhost_id));
|
||||
if (empty($user)) { // trouble
|
||||
error_log($this->errorlogtag.get_string('auth_dbusernotexist', 'auth_db', '', $username));
|
||||
print_error('auth_dbusernotexist', 'auth_db', '', $username);
|
||||
die;
|
||||
}
|
||||
|
||||
// Protect the userid from being overwritten
|
||||
$userid = $user->id;
|
||||
|
||||
if ($newinfo = $this->get_userinfo($username)) {
|
||||
$newinfo = truncate_userinfo($newinfo);
|
||||
|
||||
if (empty($updatekeys)) { // all keys? this does not support removing values
|
||||
$updatekeys = array_keys($newinfo);
|
||||
}
|
||||
|
||||
if (!empty($updatekeys)) {
|
||||
$newuser = new stdClass();
|
||||
$newuser->id = $userid;
|
||||
// The cast to int is a workaround for MDL-53959.
|
||||
$newuser->suspended = (int)$this->is_user_suspended((object) $newinfo);
|
||||
|
||||
foreach ($updatekeys as $key) {
|
||||
if (isset($newinfo[$key])) {
|
||||
$value = $newinfo[$key];
|
||||
} else {
|
||||
$value = '';
|
||||
}
|
||||
|
||||
if (!empty($this->config->{'field_updatelocal_' . $key})) {
|
||||
// Only update if it's changed.
|
||||
if ($user->{$key} != $value) {
|
||||
$newuser->$key = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
user_update_user($newuser, false, $triggerevent);
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return $DB->get_record('user', array('id'=>$userid, 'deleted'=>0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Bulk insert in SQL's temp table
|
||||
*/
|
||||
@ -1201,6 +1145,14 @@ class auth_plugin_ldap extends auth_plugin_base {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Load old custom fields.
|
||||
profile_load_custom_fields($olduser, false);
|
||||
|
||||
$fields = array();
|
||||
foreach (profile_get_custom_fields(false) as $field) {
|
||||
$fields[$field->shortname] = $field;
|
||||
}
|
||||
|
||||
$success = true;
|
||||
$user_info_result = ldap_read($ldapconnection, $user_dn, '(objectClass=*)', $search_attribs);
|
||||
if ($user_info_result) {
|
||||
@ -1219,19 +1171,24 @@ class auth_plugin_ldap extends auth_plugin_base {
|
||||
$user_entry = $user_entry[0];
|
||||
|
||||
foreach ($attrmap as $key => $ldapkeys) {
|
||||
$profilefield = '';
|
||||
// Only process if the moodle field ($key) has changed and we
|
||||
// are set to update LDAP with it
|
||||
$customprofilefield = 'profile_field_' . $key;
|
||||
if (isset($olduser->$key) and isset($newuser->$key)
|
||||
and ($olduser->$key !== $newuser->$key)) {
|
||||
$profilefield = $key;
|
||||
} else if (isset($olduser->$customprofilefield) && isset($newuser->$customprofilefield)
|
||||
&& $olduser->$customprofilefield !== $newuser->$customprofilefield) {
|
||||
$profilefield = $customprofilefield;
|
||||
if (preg_match('/^profile_field_(.*)$/', $key, $match)) {
|
||||
// Custom field.
|
||||
$fieldname = $match[1];
|
||||
if (isset($fields[$fieldname])) {
|
||||
$class = 'profile_field_' . $fields[$fieldname]->datatype;
|
||||
$formfield = new $class($fields[$fieldname]->id, $olduser->id);
|
||||
$oldvalue = isset($olduser->profile[$fieldname]) ? $olduser->profile[$fieldname] : null;
|
||||
} else {
|
||||
$oldvalue = null;
|
||||
}
|
||||
$newvalue = $formfield->edit_save_data_preprocess($newuser->{$formfield->inputname}, new stdClass);
|
||||
} else {
|
||||
// Standard field.
|
||||
$oldvalue = isset($olduser->$key) ? $olduser->$key : null;
|
||||
$newvalue = isset($newuser->$key) ? $newuser->$key : null;
|
||||
}
|
||||
|
||||
if (!empty($profilefield) && !empty($this->config->{'field_updateremote_' . $key})) {
|
||||
if ($newvalue !== null and $newvalue !== $oldvalue and !empty($this->config->{'field_updateremote_' . $key})) {
|
||||
// For ldap values that could be in more than one
|
||||
// ldap key, we will do our best to match
|
||||
// where they came from
|
||||
@ -1244,9 +1201,9 @@ class auth_plugin_ldap extends auth_plugin_base {
|
||||
$ambiguous = false;
|
||||
}
|
||||
|
||||
$nuvalue = core_text::convert($newuser->$profilefield, 'utf-8', $this->config->ldapencoding);
|
||||
$nuvalue = core_text::convert($newvalue, 'utf-8', $this->config->ldapencoding);
|
||||
empty($nuvalue) ? $nuvalue = array() : $nuvalue;
|
||||
$ouvalue = core_text::convert($olduser->$profilefield, 'utf-8', $this->config->ldapencoding);
|
||||
$ouvalue = core_text::convert($oldvalue, 'utf-8', $this->config->ldapencoding);
|
||||
|
||||
foreach ($ldapkeys as $ldapkey) {
|
||||
$ldapkey = $ldapkey;
|
||||
|
@ -618,6 +618,90 @@ class auth_plugin_base {
|
||||
public function postlogout_hook($user) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a local user record from an external source.
|
||||
* This is a lighter version of the one in moodlelib -- won't do
|
||||
* expensive ops such as enrolment.
|
||||
*
|
||||
* @param string $username username
|
||||
* @param array $updatekeys fields to update, false updates all fields.
|
||||
* @param bool $triggerevent set false if user_updated event should not be triggered.
|
||||
* This will not affect user_password_updated event triggering.
|
||||
* @return stdClass|bool updated user record or false if there is no new info to update.
|
||||
*/
|
||||
protected function update_user_record($username, $updatekeys = false, $triggerevent = false) {
|
||||
global $CFG, $DB;
|
||||
|
||||
require_once($CFG->dirroot.'/user/profile/lib.php');
|
||||
|
||||
// Just in case check text case.
|
||||
$username = trim(core_text::strtolower($username));
|
||||
|
||||
// Get the current user record.
|
||||
$user = $DB->get_record('user', array('username' => $username, 'mnethostid' => $CFG->mnet_localhost_id));
|
||||
if (empty($user)) { // Trouble.
|
||||
error_log($this->errorlogtag.get_string('auth_dbusernotexist', 'auth_db', '', $username));
|
||||
print_error('auth_dbusernotexist', 'auth_db', '', $username);
|
||||
die;
|
||||
}
|
||||
|
||||
// Load all custom fields into $user->profile.
|
||||
profile_load_custom_fields($user, false);
|
||||
|
||||
// Protect the userid from being overwritten.
|
||||
$userid = $user->id;
|
||||
|
||||
$needsupdate = false;
|
||||
|
||||
if ($newinfo = $this->get_userinfo($username)) {
|
||||
$newinfo = truncate_userinfo($newinfo);
|
||||
|
||||
if (empty($updatekeys)) { // All keys? this does not support removing values.
|
||||
$updatekeys = array_keys($newinfo);
|
||||
}
|
||||
|
||||
if (!empty($updatekeys)) {
|
||||
$newuser = new stdClass();
|
||||
$newuser->id = $userid;
|
||||
$newuser->profile = array();
|
||||
|
||||
foreach ($updatekeys as $key) {
|
||||
if (isset($newinfo[$key])) {
|
||||
$value = $newinfo[$key];
|
||||
} else {
|
||||
$value = '';
|
||||
}
|
||||
|
||||
if (!empty($this->config->{'field_updatelocal_' . $key})) {
|
||||
if (preg_match('/^profile_field_(.*)$/', $key, $match)) {
|
||||
// Custom field.
|
||||
$field = $match[1];
|
||||
$currentvalue = isset($user->profile[$field]) ? $user->profile[$field] : null;
|
||||
$newuser->profile[$field] = $value;
|
||||
} else {
|
||||
// Standard field.
|
||||
$currentvalue = isset($user->$key) ? $user->$key : null;
|
||||
$newuser->$key = $value;
|
||||
}
|
||||
|
||||
// Only update if it's changed.
|
||||
if ($currentvalue !== $value) {
|
||||
$needsupdate = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($needsupdate) {
|
||||
user_update_user($newuser, false, $triggerevent);
|
||||
profile_save_custom_fields($newuser);
|
||||
return $DB->get_record('user', array('id' => $userid, 'deleted' => 0));
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of enabled identity providers.
|
||||
*
|
||||
|
@ -769,14 +769,36 @@ function profile_get_custom_fields($onlyinuserobject = false) {
|
||||
/**
|
||||
* Load custom profile fields into user object
|
||||
*
|
||||
* Please note originally in 1.9 we were using the custom field names directly,
|
||||
* but it was causing unexpected collisions when adding new fields to user table,
|
||||
* so instead we now use 'profile_' prefix.
|
||||
* @param stdClass $user user object
|
||||
* @param bool $onlyinuserobject True if you only want the ones in $USER
|
||||
*/
|
||||
function profile_load_custom_fields($user, $onlyinuserobject = true) {
|
||||
$user->profile = (array)profile_user_record($user->id, $onlyinuserobject);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save custom profile fields in user object
|
||||
*
|
||||
* @param stdClass $user user object
|
||||
*/
|
||||
function profile_load_custom_fields($user) {
|
||||
$user->profile = (array)profile_user_record($user->id);
|
||||
function profile_save_custom_fields($user) {
|
||||
global $DB;
|
||||
|
||||
if ($fields = $DB->get_records('user_info_field')) {
|
||||
foreach ($fields as $field) {
|
||||
if (isset($user->profile[$field->shortname])) {
|
||||
$conditions = array('fieldid' => $field->id, 'userid' => $user->id);
|
||||
$id = $DB->get_field('user_info_data', 'id', $conditions);
|
||||
$data = $user->profile[$field->shortname];
|
||||
if ($id) {
|
||||
$DB->set_field('user_info_data', 'data', $data, array('id' => $id));
|
||||
} else {
|
||||
$record = array('fieldid' => $field->id, 'userid' => $user->id, 'data' => $data);
|
||||
$DB->insert_record('user_info_data', $record);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user