public function Update($ID, $arFields, $authActions = true)
{
/** @global CUserTypeManager $USER_FIELD_MANAGER */
global $DB, $USER_FIELD_MANAGER, $CACHE_MANAGER, $USER;
$ID = intval($ID);
if ($ID <= 0)
{
return false;
}
if (!$this->CheckFields($arFields, $ID))
{
$result = false;
$arFields["RESULT_MESSAGE"] = &$this->LAST_ERROR;
}
else
{
unset($arFields["ID"]);
if (is_set($arFields, "ACTIVE") && $arFields["ACTIVE"] != 'Y')
{
$arFields["ACTIVE"] = 'N';
}
if (is_set($arFields, "BLOCKED") && $arFields["BLOCKED"] != 'Y')
{
$arFields["BLOCKED"] = 'N';
}
if (is_set($arFields, "PASSWORD_EXPIRED") && $arFields["PASSWORD_EXPIRED"] != 'Y')
{
$arFields["PASSWORD_EXPIRED"] = 'N';
}
if (is_set($arFields, "PERSONAL_GENDER") && ($arFields["PERSONAL_GENDER"] != "M" && $arFields["PERSONAL_GENDER"] != "F"))
{
$arFields["PERSONAL_GENDER"] = '';
}
$saveHistory = (Option::get('main', 'user_profile_history') === 'Y');
//we need old values for some actions
$arUser = null;
if ((isset($arFields["ACTIVE"]) && $arFields["ACTIVE"] == 'N') || isset($arFields["PASSWORD"]) || $saveHistory)
{
$rUser = static::GetByID($ID);
$arUser = $rUser->Fetch();
}
$originalPassword = '';
$passwordChanged = false;
if (is_set($arFields, "PASSWORD"))
{
$originalPassword = $arFields["PASSWORD"];
$arFields["PASSWORD"] = Password::hash($arFields["PASSWORD"]);
if ($arUser)
{
if (!Password::equals($arUser["PASSWORD"], $originalPassword))
{
//password changed, remove stored authentication
UserStoredAuthTable::deleteByFilter(['=USER_ID' => $ID]);
$passwordChanged = true;
}
}
if (Option::get('main', 'event_log_password_change', 'N') === 'Y')
{
CEventLog::Log('SECURITY', 'USER_PASSWORD_CHANGED', 'main', $ID);
}
if (!isset($arFields['PASSWORD_EXPIRED']))
{
// reset the flag on password change
$arFields['PASSWORD_EXPIRED'] = 'N';
}
}
unset($arFields["STORED_HASH"]);
$checkword = '';
if (!is_set($arFields, "CHECKWORD"))
{
if (is_set($arFields, "PASSWORD") || is_set($arFields, "EMAIL") || is_set($arFields, "LOGIN") || is_set($arFields, "ACTIVE"))
{
$checkword = Random::getString(32);
$arFields["CHECKWORD"] = Password::hash($checkword);
}
}
else
{
$checkword = $arFields["CHECKWORD"];
$arFields["CHECKWORD"] = Password::hash($checkword);
}
if (is_set($arFields, "CHECKWORD") && !is_set($arFields, "CHECKWORD_TIME"))
{
$arFields["~CHECKWORD_TIME"] = $DB->CurrentTimeFunction();
}
if (is_set($arFields, "WORK_COUNTRY"))
{
$arFields["WORK_COUNTRY"] = intval($arFields["WORK_COUNTRY"]);
}
if (is_set($arFields, "PERSONAL_COUNTRY"))
{
$arFields["PERSONAL_COUNTRY"] = intval($arFields["PERSONAL_COUNTRY"]);
}
if (
array_key_exists("PERSONAL_PHOTO", $arFields)
&& is_array($arFields["PERSONAL_PHOTO"])
&& (
!array_key_exists("MODULE_ID", $arFields["PERSONAL_PHOTO"])
|| $arFields["PERSONAL_PHOTO"]["MODULE_ID"] == ''
)
)
{
$arFields["PERSONAL_PHOTO"]["MODULE_ID"] = 'main';
}
CFile::SaveForDB($arFields, 'PERSONAL_PHOTO', 'main');
if (
array_key_exists("WORK_LOGO", $arFields)
&& is_array($arFields["WORK_LOGO"])
&& (
!array_key_exists("MODULE_ID", $arFields["WORK_LOGO"])
|| $arFields["WORK_LOGO"]["MODULE_ID"] == ''
)
)
{
$arFields["WORK_LOGO"]["MODULE_ID"] = 'main';
}
CFile::SaveForDB($arFields, 'WORK_LOGO', 'main');
$strUpdate = $DB->PrepareUpdate("b_user", $arFields);
if (!is_set($arFields, "TIMESTAMP_X"))
{
$strUpdate .= ($strUpdate != '' ? ',' : '') . " TIMESTAMP_X = " . $DB->GetNowFunction();
}
$strSql = "UPDATE b_user SET " . $strUpdate . " WHERE ID=" . $ID;
$DB->Query($strSql);
$USER_FIELD_MANAGER->Update("USER", $ID, $arFields);
if (isset($arFields["PHONE_NUMBER"]))
{
$numberExists = false;
if ($arFields["PHONE_NUMBER"] != '')
{
$arFields["PHONE_NUMBER"] = MainUserPhoneAuthTable::normalizePhoneNumber($arFields["PHONE_NUMBER"]);
$numberExists = MainUserPhoneAuthTable::getList(["filter" => [
"=USER_ID" => $ID,
"=PHONE_NUMBER" => $arFields["PHONE_NUMBER"],
]])->fetch();
}
if ($arFields["PHONE_NUMBER"] == '' || !$numberExists)
{
//number changed or added
MainUserPhoneAuthTable::delete($ID);
if ($arFields["PHONE_NUMBER"] != '')
{
MainUserPhoneAuthTable::add([
"USER_ID" => $ID,
"PHONE_NUMBER" => $arFields["PHONE_NUMBER"],
]);
}
}
}
if (Option::get('main', 'event_log_user_edit', 'N') === 'Y')
{
$res_log["user"] = ($arFields["NAME"] != '' || $arFields["LAST_NAME"] != '') ? trim($arFields["NAME"] . ' ' . $arFields["LAST_NAME"]) : $arFields["LOGIN"];
CEventLog::Log('SECURITY', 'USER_EDIT', 'main', $ID, serialize($res_log));
}
if (is_set($arFields, "GROUP_ID"))
{
static::SetUserGroup($ID, $arFields["GROUP_ID"]);
}
if ($arUser && $passwordChanged)
{
if (Option::get('main', 'use_digest_auth', 'N') == 'Y')
{
//update digest hash for http digest authorization
static::UpdateDigest($arUser["ID"], $originalPassword);
}
//history of passwords
UserPasswordTable::add([
"USER_ID" => $arUser["ID"],
"PASSWORD" => $arFields["PASSWORD"],
"DATE_CHANGE" => new MainTypeDateTime(),
]);
}
if ($arUser && $authActions)
{
$authAction = false;
if (isset($arFields["ACTIVE"]) && $arUser["ACTIVE"] == 'Y' && $arFields["ACTIVE"] == 'N')
{
$authAction = true;
}
$internalUser = true;
if (isset($arFields["EXTERNAL_AUTH_ID"]))
{
if ($arFields["EXTERNAL_AUTH_ID"] != '')
{
$internalUser = false;
}
}
elseif ($arUser["EXTERNAL_AUTH_ID"] != '')
{
$internalUser = false;
}
if ($internalUser && isset($arFields["PASSWORD"]) && $passwordChanged)
{
$authAction = true;
if (is_object($USER) && $USER->GetID() == $ID)
{
//changed password by himself
$USER->SetParam("AUTH_ACTION_SKIP_LOGOUT", true);
}
}
if ($authAction)
{
MainUserAuthActionTable::addLogoutAction($ID);
}
}
$result = true;
$arFields["CHECKWORD"] = $checkword;
//update session information and cache for current user
if (is_object($USER) && $USER->GetID() == $ID)
{
static $arSessFields = [
'LOGIN' => 'LOGIN',
'EMAIL' => 'EMAIL',
'TITLE' => 'TITLE',
'FIRST_NAME' => 'NAME',
'SECOND_NAME' => 'SECOND_NAME',
'LAST_NAME' => 'LAST_NAME',
'PERSONAL_PHOTO' => 'PERSONAL_PHOTO',
'PERSONAL_GENDER' => 'PERSONAL_GENDER',
'AUTO_TIME_ZONE' => 'AUTO_TIME_ZONE',
'TIME_ZONE' => 'TIME_ZONE',
];
foreach ($arSessFields as $key => $val)
{
if (isset($arFields[$val]))
{
$USER->SetParam($key, $arFields[$val]);
}
}
$name = $USER->GetParam("FIRST_NAME");
$last_name = $USER->GetParam("LAST_NAME");
$USER->SetParam("NAME", $name . ($name == '' || $last_name == '' ? '' : ' ') . $last_name);
//cache for GetByID()
self::$CURRENT_USER = false;
}
if ($saveHistory && $arUser)
{
$rUser = static::GetByID($ID);
$newUser = $rUser->Fetch();
UserProfileHistoryTable::addHistory($ID, UserProfileHistoryTable::TYPE_UPDATE, $arUser, $newUser);
}
}
$arFields["ID"] = $ID;
$arFields["RESULT"] = &$result;
foreach (GetModuleEvents('main', 'OnAfterUserUpdate', true) as $arEvent)
{
ExecuteModuleEventEx($arEvent, [&$arFields]);
}
if ($arFields["RESULT"])
{
MainUserTable::indexRecord($ID);
if (defined("BX_COMP_MANAGED_CACHE"))
{
$userData = MainUserTable::getById($ID)->fetch();
$isRealUser = !$userData['EXTERNAL_AUTH_ID'] || !in_array($userData['EXTERNAL_AUTH_ID'], MainUserTable::getExternalUserTypes());
$CACHE_MANAGER->ClearByTag("USER_CARD_" . intval($ID / TAGGED_user_card_size));
$CACHE_MANAGER->ClearByTag($isRealUser ? "USER_CARD" : "EXTERNAL_USER_CARD");
static $arNameFields = [
"NAME", "LAST_NAME", "SECOND_NAME",
"ACTIVE",
"LOGIN", "EMAIL",
"PERSONAL_GENDER", "PERSONAL_PHOTO", "WORK_POSITION", "PERSONAL_PROFESSION", "PERSONAL_WWW", "PERSONAL_BIRTHDAY", "TITLE",
"EXTERNAL_AUTH_ID", "UF_DEPARTMENT",
"AUTO_TIME_ZONE", "TIME_ZONE", "TIME_ZONE_OFFSET",
];
$bClear = false;
foreach ($arNameFields as $val)
{
if (isset($arFields[$val]))
{
$bClear = true;
break;
}
}
if ($bClear)
{
$CACHE_MANAGER->ClearByTag("USER_NAME_" . $ID);
$CACHE_MANAGER->ClearByTag($isRealUser ? "USER_NAME" : "EXTERNAL_USER_NAME");
}
}
}
return $result;
}