private function restoreOne($Log, $DeleteLog = true)
{
// Throw an event to see if the restore is being overridden.
$Handled = false;
$this->EventArguments['Handled'] =& $Handled;
$this->EventArguments['Log'] =& $Log;
$this->fireEvent('BeforeRestore');
if ($Handled) {
return;
// a plugin handled the restore.
}
if ($Log['RecordType'] == 'Configuration') {
throw new Gdn_UserException('Restoring configuration edits is currently not supported.');
}
if ($Log['RecordType'] == 'Registration') {
$TableName = 'User';
} else {
$TableName = $Log['RecordType'];
}
$Data = $Log['Data'];
if (isset($Data['Attributes'])) {
$Attr = 'Attributes';
} elseif (isset($Data['Data'])) {
$Attr = 'Data';
} else {
$Attr = '';
}
if ($Attr) {
if (is_string($Data[$Attr])) {
$Data[$Attr] = dbdecode($Data[$Attr]);
}
// Record a bit of information about the restoration.
if (!is_array($Data[$Attr])) {
$Data[$Attr] = [];
}
$Data[$Attr]['RestoreUserID'] = Gdn::session()->UserID;
$Data[$Attr]['DateRestored'] = Gdn_Format::toDateTime();
}
if (!isset($Columns[$TableName])) {
$Columns[$TableName] = Gdn::sql()->fetchColumns($TableName);
}
$Set = array_flip($Columns[$TableName]);
// Set the sets from the data.
foreach ($Set as $Key => $Value) {
if (isset($Data[$Key])) {
$Value = $Data[$Key];
if (is_array($Value)) {
$Value = dbencode($Value);
}
$Set[$Key] = $Value;
} else {
unset($Set[$Key]);
}
}
switch ($Log['Operation']) {
case 'Edit':
// We are restoring an edit so just update the record.
$IDColumn = $Log['RecordType'] . 'ID';
$Where = [$IDColumn => $Log['RecordID']];
unset($Set[$IDColumn]);
Gdn::sql()->put($TableName, $Set, $Where);
break;
case 'Delete':
case 'Spam':
case 'Moderate':
case 'Pending':
case 'Ban':
if (!$Log['RecordID']) {
// This log entry was never in the table.
if (isset($Set['DateInserted'])) {
$Set['DateInserted'] = Gdn_Format::toDateTime();
}
}
// Insert the record back into the db.
if ($Log['Operation'] == 'Spam' && $Log['RecordType'] == 'Registration') {
saveToConfig(['Garden.Registration.NameUnique' => false, 'Garden.Registration.EmailUnique' => false], '', false);
if (isset($Data['Username'])) {
$Set['Name'] = $Data['Username'];
}
$ID = Gdn::userModel()->insertForBasic($Set, false, ['ValidateSpam' => false]);
if (!$ID) {
throw new Exception(Gdn::userModel()->Validation->resultsText());
} else {
Gdn::userModel()->sendWelcomeEmail($ID, '', 'Register');
}
} else {
$ID = Gdn::sql()->options('Replace', true)->insert($TableName, $Set);
if (!$ID && isset($Log['RecordID'])) {
$ID = $Log['RecordID'];
}
// Unban a user.
if ($Log['RecordType'] == 'User' && $Log['Operation'] == 'Ban') {
Gdn::userModel()->setField($ID, 'Banned', 0);
}
// Keep track of a discussion ID so that its count can be recalculated.
if ($Log['Operation'] != 'Edit') {
switch ($Log['RecordType']) {
case 'Discussion':
$this->recalcIDs['Discussion'][$ID] = true;
break;
case 'Comment':
$this->recalcIDs['Discussion'][$Log['ParentRecordID']] = true;
break;
}
}
if ($Log['Operation'] == 'Pending') {
switch ($Log['RecordType']) {
case 'Discussion':
if (val('UserDiscussion', $this->recalcIDs) && val($Log['RecordUserID'], $this->recalcIDs['UserDiscussion'])) {
$this->recalcIDs['UserDiscussion'][$Log['RecordUserID']]++;
} else {
$this->recalcIDs['UserDiscussion'][$Log['RecordUserID']] = 1;
}
break;
case 'Comment':
if (val('UserComment', $this->recalcIDs) && val($Log['RecordUserID'], $this->recalcIDs['UserComment'])) {
$this->recalcIDs['UserComment'][$Log['RecordUserID']]++;
} else {
$this->recalcIDs['UserComment'][$Log['RecordUserID']] = 1;
}
break;
}
}
}
break;
}
// Fire 'after' event
if (isset($ID)) {
$this->EventArguments['InsertID'] = $ID;
}
$this->fireEvent('AfterRestore');
if ($DeleteLog) {
Gdn::sql()->delete('Log', ['LogID' => $Log['LogID']]);
}
}