Skip to content

Commit

Permalink
Fixed issue #18655: Unnoticed data loss if field in response table it…
Browse files Browse the repository at this point in the history
… missing (#2946)
  • Loading branch information
gabrieljenik committed Feb 27, 2023
1 parent d4665dd commit aa1a887
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 1 deletion.
40 changes: 39 additions & 1 deletion application/helpers/expressions/em_manager_helper.php
Expand Up @@ -5159,7 +5159,16 @@ private function _UpdateValuesInDatabase($finished = false)
return;
}
if ($oResponse->submitdate == null || Survey::model()->findByPk($this->sid)->alloweditaftercompletion == 'Y') {
$oResponse->setAttributes($aResponseAttributes, false);
try {
$oResponse->setAttributes($aResponseAttributes, false);
} catch (Exception $ex) {
// This can happen if the table is missing fields. It should never happen, but somehow it does.
submitfailed($ex->getMessage());
if (YII_DEBUG) {
throw $ex;
}
$this->throwFatalError();
}
$oResponse->decrypt();
if (!$oResponse->encryptSave()) {
$message = submitfailed('', print_r($oResponse->getErrors(), true)); // $response->getErrors() is array[string[]], then can not join
Expand Down Expand Up @@ -9952,6 +9961,35 @@ public function getUpdatedValues(): array
{
return $this->updatedValues;
}

/**
* Kills the survey session and throws an exception with the specified message.
* @param string $message If empty, a default message is used.
* @throws Exception
*/
private function throwFatalError($message = null)
{
if (empty($message)) {
$surveyInfo = getSurveyInfo($this->sid, $_SESSION['LEMlang']);
if (!empty($surveyInfo['admin'])) {
$message = sprintf(
$this->gT("Due to a technical problem, your response could not be saved. Please contact the survey administrator %s (%s) about this problem. You will not be able to proceed with this survey."),
$surveyInfo['admin'],
$surveyInfo['adminemail']
);
} elseif (!empty(Yii::app()->getConfig("siteadminname"))) {
$message = sprintf(
$this->gT("Due to a technical problem, your response could not be saved. Please contact the survey administrator %s (%s) about this problem. You will not be able to proceed with this survey."),
Yii::app()->getConfig("siteadminname"),
Yii::app()->getConfig("siteadminemail")
);
} else {
$message = $this->gT("Due to a technical problem, your response could not be saved. You will not be able to proceed with this survey.");
}
}
killSurveySession($this->sid);
throw new Exception($message);
}
}

/**
Expand Down
22 changes: 22 additions & 0 deletions application/models/Response.php
Expand Up @@ -255,4 +255,26 @@ public static function getEncryptedAttributes($surveyid = 0)
}
return $aAttributes;
}

/**
* Override to throw Exception when attribute is missing, as we need to avoid
* data loss in case of mismatch between survey structure and table schema.
* @inheritdoc
*/
public function setAttributes($values, $safeOnly = true)
{
if (!is_array($values)) {
return;
}
$attributes = array_flip($safeOnly ? $this->getSafeAttributeNames() : $this->attributeNames());
foreach ($values as $name => $value) {
if (isset($attributes[$name])) {
$this->$name = $value;
} elseif ($safeOnly) {
$this->onUnsafeAttribute($name, $value);
} else {
throw new Exception(sprintf("Attribute '%s' not found in the model.", $name));
}
}
}
}

0 comments on commit aa1a887

Please sign in to comment.