N°4157 - Relations, modify one and add it again fails, the adding is ignored - check uniqueness rule before saving object

This commit is contained in:
acognet
2022-07-08 12:15:46 +02:00
parent c56cb516ed
commit 5a77159ece

View File

@@ -2062,15 +2062,13 @@ abstract class DBObject implements iDisplay
if ($bHasDuplicates)
{
$bIsBlockingRule = $aUniquenessRuleProperties['is_blocking'];
if (is_null($bIsBlockingRule))
{
if (is_null($bIsBlockingRule)) {
$bIsBlockingRule = true;
}
$sErrorMessage = $this->GetUniquenessRuleMessage($sUniquenessRuleId);
$sErrorMessage = $this->GetUniquenessRuleMessage($sUniquenessRuleId, $this);
if ($bIsBlockingRule)
{
if ($bIsBlockingRule) {
$this->m_aCheckIssues[] = $sErrorMessage;
continue;
}
@@ -2081,32 +2079,32 @@ abstract class DBObject implements iDisplay
}
/**
*
* @internal
*
*
* @internal
*
* @param string $sUniquenessRuleId
* @param DBObject $oObj
*
* @return string dict key : Class:$sClassName/UniquenessRule:$sUniquenessRuleId if none then will use Core:UniquenessDefaultError
* Dictionary keys can contain "$this" placeholders
*
* @since 2.6.0 N°659 uniqueness constraint
*/
protected function GetUniquenessRuleMessage($sUniquenessRuleId)
protected function GetUniquenessRuleMessage($sUniquenessRuleId, $oObj)
{
$sCurrentClass = get_class($this);
$sCurrentClass = get_class($oObj);
$sClass = MetaModel::GetRootClassForUniquenessRule($sUniquenessRuleId, $sCurrentClass);
$sMessageKey = "Class:$sClass/UniquenessRule:$sUniquenessRuleId";
$sTemplate = Dict::S($sMessageKey, '');
if (empty($sTemplate))
{
if (empty($sTemplate)) {
// we could add also a specific message if user is admin ("dict key is missing")
return Dict::Format('Core:UniquenessDefaultError', $sUniquenessRuleId);
}
$oString = new TemplateString($sTemplate);
return $oString->Render(array('this' => $this));
return $oString->Render(array('this' => $oObj));
}
/**
@@ -2205,20 +2203,41 @@ abstract class DBObject implements iDisplay
$aCurrentRemoteIds = [];
$aDuplicatesFields = [];
$value->rewind();
$oOneLnkFaill = null;
while ($oCurrentLnk = $value->current()) {
$iExtKeyToRemote = $oCurrentLnk->Get($sExtKeyToRemote);
if (isset($aCurrentRemoteIds[$iExtKeyToRemote])) {
$aDuplicatesFields[] = $oCurrentLnk->Get($sExtKeyToRemote.'_friendlyname');
} else {
$aCurrentRemoteIds[$iExtKeyToRemote] = true;
$oOneLnkFaill = $oCurrentLnk;
}
$value->next();
}
if (!empty($aDuplicatesFields)) {
$this->m_aCheckWarnings[] = Dict::Format('Core:AttributeLinkedSetDuplicatesFound',
$oAttDef->GetLabel(),
implode(', ', $aDuplicatesFields));
//check uniqueness rule in order to stop saving object if necessary
$sCurrentClass = $value->GetClass();
$aUniquenessRules = MetaModel::GetUniquenessRules($sCurrentClass);
foreach ($aUniquenessRules as $sUniquenessRuleId => $aUniquenessRuleProperties) {
$bIsBlockingRule = $aUniquenessRuleProperties['is_blocking'];
if (is_null($bIsBlockingRule)) {
$bIsBlockingRule = true;
}
if ($bIsBlockingRule || $aUniquenessRuleProperties['disabled'] === true) {
$sErrorMessage = $this->GetUniquenessRuleMessage($sUniquenessRuleId, $oOneLnkFaill);
$this->m_aCheckIssues[] = $sErrorMessage;
$this->m_aCheckIssues[] = Dict::Format('Core:AttributeLinkedSetDuplicatesFound',
$oAttDef->GetLabel(),
implode(', ', $aDuplicatesFields));
} else {
$this->m_aCheckWarnings[] = Dict::Format('Core:AttributeLinkedSetDuplicatesFound',
$oAttDef->GetLabel(),
implode(', ', $aDuplicatesFields));
}
}
}
}
@@ -3174,8 +3193,7 @@ abstract class DBObject implements iDisplay
$this->OnUpdate();
$aChanges = $this->ListChanges();
if (count($aChanges) == 0)
{
if (count($aChanges) == 0) {
// Attempting to update an unchanged object
unset($aUpdateReentrance[$sKey]);
@@ -3184,12 +3202,11 @@ abstract class DBObject implements iDisplay
// Ultimate check - ensure DB integrity
list($bRes, $aIssues) = $this->CheckToWrite();
if (!$bRes)
{
if (!$bRes) {
throw new CoreCannotSaveObjectException(array(
'issues' => $aIssues,
'class' => get_class($this),
'id' => $this->GetKey()
'class' => get_class($this),
'id' => $this->GetKey(),
));
}
@@ -3283,8 +3300,7 @@ abstract class DBObject implements iDisplay
}
// Update scalar attributes
if (count($aDBChanges) != 0)
{
if (count($aDBChanges) != 0) {
$oFilter = new DBObjectSearch(get_class($this));
$oFilter->AddCondition('id', $this->m_iKey, '=');
$oFilter->AllowAllData();