mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-13 23:44:11 +01:00
Compare commits
3 Commits
feature/fa
...
feature/41
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2363f2fb21 | ||
|
|
c7eea3f51f | ||
|
|
5a77159ece |
@@ -677,33 +677,26 @@ HTML
|
||||
$sTargetClass = $oLinkingAttDef->GetTargetClass();
|
||||
// n:n links => must be allowed to modify the linking class AND read the target class in order to edit the linkedset
|
||||
if (!UserRights::IsActionAllowed($sLinkedClass,
|
||||
UR_ACTION_MODIFY) || !UserRights::IsActionAllowed($sTargetClass, UR_ACTION_READ))
|
||||
{
|
||||
UR_ACTION_MODIFY) || !UserRights::IsActionAllowed($sTargetClass, UR_ACTION_READ)) {
|
||||
$iFlags |= OPT_ATT_READONLY;
|
||||
}
|
||||
// n:n links => must be allowed to read the linking class AND the target class in order to display the linkedset
|
||||
if (!UserRights::IsActionAllowed($sLinkedClass,
|
||||
UR_ACTION_READ) || !UserRights::IsActionAllowed($sTargetClass, UR_ACTION_READ))
|
||||
{
|
||||
UR_ACTION_READ) || !UserRights::IsActionAllowed($sTargetClass, UR_ACTION_READ)) {
|
||||
$iFlags |= OPT_ATT_HIDDEN;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// 1:n links => must be allowed to modify the linked class in order to edit the linkedset
|
||||
if (!UserRights::IsActionAllowed($sLinkedClass, UR_ACTION_MODIFY))
|
||||
{
|
||||
if (!UserRights::IsActionAllowed($sLinkedClass, UR_ACTION_MODIFY)) {
|
||||
$iFlags |= OPT_ATT_READONLY;
|
||||
}
|
||||
// 1:n links => must be allowed to read the linked class in order to display the linkedset
|
||||
if (!UserRights::IsActionAllowed($sLinkedClass, UR_ACTION_READ))
|
||||
{
|
||||
if (!UserRights::IsActionAllowed($sLinkedClass, UR_ACTION_READ)) {
|
||||
$iFlags |= OPT_ATT_HIDDEN;
|
||||
}
|
||||
}
|
||||
// Non-readable/hidden linkedset... don't display anything
|
||||
if ($iFlags & OPT_ATT_HIDDEN)
|
||||
{
|
||||
if ($iFlags & OPT_ATT_HIDDEN) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -712,17 +705,13 @@ HTML
|
||||
|
||||
$aArgs = array('this' => $this);
|
||||
$bReadOnly = ($iFlags & (OPT_ATT_READONLY | OPT_ATT_SLAVE));
|
||||
if ($bEditMode && (!$bReadOnly))
|
||||
{
|
||||
if ($bEditMode && (!$bReadOnly)) {
|
||||
$sInputId = $this->m_iFormId.'_'.$sAttCode;
|
||||
|
||||
if ($oAttDef->IsIndirect())
|
||||
{
|
||||
if ($oAttDef->IsIndirect()) {
|
||||
$oLinkingAttDef = MetaModel::GetAttributeDef($sLinkedClass, $oAttDef->GetExtKeyToRemote());
|
||||
$sTargetClass = $oLinkingAttDef->GetTargetClass();
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$sTargetClass = $sLinkedClass;
|
||||
}
|
||||
|
||||
@@ -732,7 +721,7 @@ HTML
|
||||
|
||||
$sDisplayValue = ''; // not used
|
||||
$sHTMLValue = "<span id=\"field_{$sInputId}\">".self::GetFormElementForField($oPage, $sClass, $sAttCode,
|
||||
$oAttDef, $oLinkSet, $sDisplayValue, $sInputId, '', $iFlags, $aArgs).'</span>';
|
||||
$oAttDef, $oOrmLinkSet, $sDisplayValue, $sInputId, '', $iFlags, $aArgs).'</span>';
|
||||
$this->AddToFieldsMap($sAttCode, $sInputId);
|
||||
$oPage->add($sHTMLValue);
|
||||
}
|
||||
@@ -2377,8 +2366,7 @@ EOF
|
||||
case 'LinkedSet':
|
||||
$sInputType = self::ENUM_INPUT_TYPE_LINKEDSET;
|
||||
if ($oAttDef->IsIndirect()) {
|
||||
$oWidget = new UILinksWidget($sClass, $sAttCode, $iId, $sNameSuffix,
|
||||
$oAttDef->DuplicatesAllowed());
|
||||
$oWidget = new UILinksWidget($sClass, $sAttCode, $iId, $sNameSuffix, $oAttDef->DuplicatesAllowed());
|
||||
} else {
|
||||
$oWidget = new UILinksWidgetDirect($sClass, $sAttCode, $iId, $sNameSuffix);
|
||||
}
|
||||
@@ -4025,18 +4013,14 @@ HTML;
|
||||
$this->Set($sAttCode, $value);
|
||||
break;
|
||||
case 'LinkedSet':
|
||||
if ($this->IsValueModified($value))
|
||||
{
|
||||
if ($this->IsValueModified($value)) {
|
||||
$oLinkSet = $this->Get($sAttCode);
|
||||
$sLinkedClass = $oAttDef->GetLinkedClass();
|
||||
if (array_key_exists('to_be_created', $value) && (count($value['to_be_created']) > 0))
|
||||
{
|
||||
if (array_key_exists('to_be_created', $value) && (count($value['to_be_created']) > 0)) {
|
||||
// Now handle the links to be created
|
||||
foreach ($value['to_be_created'] as $aData)
|
||||
{
|
||||
foreach ($value['to_be_created'] as $aData) {
|
||||
$sSubClass = $aData['class'];
|
||||
if (($sLinkedClass == $sSubClass) || (is_subclass_of($sSubClass, $sLinkedClass)))
|
||||
{
|
||||
if (($sLinkedClass == $sSubClass) || (is_subclass_of($sSubClass, $sLinkedClass))) {
|
||||
$aObjData = $aData['data'];
|
||||
$oLink = MetaModel::NewObject($sSubClass);
|
||||
$oLink->UpdateObjectFromArray($aObjData);
|
||||
@@ -4248,28 +4232,20 @@ HTML;
|
||||
|
||||
case 'LinkedSet':
|
||||
/** @var AttributeLinkedSet $oAttDef */
|
||||
$aRawToBeCreated = json_decode(utils::ReadPostedParam("attr_{$sFormPrefix}{$sAttCode}_tbc", '{}',
|
||||
'raw_data'), true);
|
||||
$aRawToBeCreated = json_decode(utils::ReadPostedParam("attr_{$sFormPrefix}{$sAttCode}_tbc", '{}', 'raw_data'), true);
|
||||
$aToBeCreated = array();
|
||||
foreach($aRawToBeCreated as $aData)
|
||||
{
|
||||
foreach ($aRawToBeCreated as $aData) {
|
||||
$sSubFormPrefix = $aData['formPrefix'];
|
||||
$sObjClass = isset($aData['class']) ? $aData['class'] : $oAttDef->GetLinkedClass();
|
||||
$aObjData = array();
|
||||
foreach($aData as $sKey => $value)
|
||||
{
|
||||
if (preg_match("/^attr_$sSubFormPrefix(.*)$/", $sKey, $aMatches))
|
||||
{
|
||||
foreach ($aData as $sKey => $value) {
|
||||
if (preg_match("/^attr_$sSubFormPrefix(.*)$/", $sKey, $aMatches)) {
|
||||
$oLinkAttDef = MetaModel::GetAttributeDef($sObjClass, $aMatches[1]);
|
||||
// Recursing over n:n link datetime attributes
|
||||
// Note: We might need to do it with other attribute types, like Document or redundancy setting.
|
||||
if ($oLinkAttDef instanceof AttributeDateTime)
|
||||
{
|
||||
$aObjData[$aMatches[1]] = $this->PrepareValueFromPostedForm($sSubFormPrefix,
|
||||
$aMatches[1], $sObjClass, $aData);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($oLinkAttDef instanceof AttributeDateTime) {
|
||||
$aObjData[$aMatches[1]] = $this->PrepareValueFromPostedForm($sSubFormPrefix, $aMatches[1], $sObjClass, $aData);
|
||||
} else {
|
||||
$aObjData[$aMatches[1]] = $value;
|
||||
}
|
||||
}
|
||||
@@ -4277,28 +4253,20 @@ HTML;
|
||||
$aToBeCreated[] = array('class' => $sObjClass, 'data' => $aObjData);
|
||||
}
|
||||
|
||||
$aRawToBeModified = json_decode(utils::ReadPostedParam("attr_{$sFormPrefix}{$sAttCode}_tbm", '{}',
|
||||
'raw_data'), true);
|
||||
$aRawToBeModified = json_decode(utils::ReadPostedParam("attr_{$sFormPrefix}{$sAttCode}_tbm", '{}', 'raw_data'), true);
|
||||
$aToBeModified = array();
|
||||
foreach($aRawToBeModified as $iObjKey => $aData)
|
||||
{
|
||||
foreach ($aRawToBeModified as $iObjKey => $aData) {
|
||||
$sSubFormPrefix = $aData['formPrefix'];
|
||||
$sObjClass = isset($aData['class']) ? $aData['class'] : $oAttDef->GetLinkedClass();
|
||||
$aObjData = array();
|
||||
foreach($aData as $sKey => $value)
|
||||
{
|
||||
if (preg_match("/^attr_$sSubFormPrefix(.*)$/", $sKey, $aMatches))
|
||||
{
|
||||
foreach ($aData as $sKey => $value) {
|
||||
if (preg_match("/^attr_$sSubFormPrefix(.*)$/", $sKey, $aMatches)) {
|
||||
$oLinkAttDef = MetaModel::GetAttributeDef($sObjClass, $aMatches[1]);
|
||||
// Recursing over n:n link datetime attributes
|
||||
// Note: We might need to do it with other attribute types, like Document or redundancy setting.
|
||||
if ($oLinkAttDef instanceof AttributeDateTime)
|
||||
{
|
||||
$aObjData[$aMatches[1]] = $this->PrepareValueFromPostedForm($sSubFormPrefix,
|
||||
$aMatches[1], $sObjClass, $aData);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($oLinkAttDef instanceof AttributeDateTime) {
|
||||
$aObjData[$aMatches[1]] = $this->PrepareValueFromPostedForm($sSubFormPrefix, $aMatches[1], $sObjClass, $aData);
|
||||
} else {
|
||||
$aObjData[$aMatches[1]] = $value;
|
||||
}
|
||||
}
|
||||
@@ -4307,14 +4275,11 @@ HTML;
|
||||
}
|
||||
|
||||
$value = array(
|
||||
'to_be_created' => $aToBeCreated,
|
||||
'to_be_created' => $aToBeCreated,
|
||||
'to_be_modified' => $aToBeModified,
|
||||
'to_be_deleted' => json_decode(utils::ReadPostedParam("attr_{$sFormPrefix}{$sAttCode}_tbd", '[]',
|
||||
'raw_data'), true),
|
||||
'to_be_added' => json_decode(utils::ReadPostedParam("attr_{$sFormPrefix}{$sAttCode}_tba", '[]',
|
||||
'raw_data'), true),
|
||||
'to_be_removed' => json_decode(utils::ReadPostedParam("attr_{$sFormPrefix}{$sAttCode}_tbr", '[]',
|
||||
'raw_data'), true),
|
||||
'to_be_deleted' => json_decode(utils::ReadPostedParam("attr_{$sFormPrefix}{$sAttCode}_tbd", '[]', 'raw_data'), true),
|
||||
'to_be_added' => json_decode(utils::ReadPostedParam("attr_{$sFormPrefix}{$sAttCode}_tba", '[]', 'raw_data'), true),
|
||||
'to_be_removed' => json_decode(utils::ReadPostedParam("attr_{$sFormPrefix}{$sAttCode}_tbr", '[]', 'raw_data'), true),
|
||||
);
|
||||
break;
|
||||
|
||||
|
||||
@@ -108,15 +108,14 @@ class UILinksWidget
|
||||
* @throws \CoreUnexpectedValue
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function GetFormRow(WebPage $oP, DBObject $oLinkedObj, $linkObjOrId, $aArgs, $oCurrentObj, $iUniqueId, $bReadOnly = false)
|
||||
protected function GetFormRow(WebPage $oP, DBObject $oLinkedObj, $linkObjOrId, $aArgs, $oCurrentObj, $iUniqueId, $bReadOnly = false, $bModified = false)
|
||||
{
|
||||
$sPrefix = "$this->m_sAttCode{$this->m_sNameSuffix}";
|
||||
$aRow = array();
|
||||
$aFieldsMap = array();
|
||||
$iKey = 0;
|
||||
|
||||
if (is_object($linkObjOrId) && (!$linkObjOrId->IsNew()))
|
||||
{
|
||||
if (is_object($linkObjOrId) && (!$linkObjOrId->IsNew())) {
|
||||
$iKey = $linkObjOrId->GetKey();
|
||||
$iRemoteObjKey = $linkObjOrId->Get($this->m_sExtKeyToRemote);
|
||||
$sPrefix .= "[$iKey][";
|
||||
@@ -125,49 +124,44 @@ class UILinksWidget
|
||||
$aArgs['wizHelper'] = "oWizardHelper{$this->m_iInputId}{$iKey}";
|
||||
$aArgs['this'] = $linkObjOrId;
|
||||
|
||||
if ($bReadOnly)
|
||||
{
|
||||
if ($bReadOnly) {
|
||||
$aRow['form::checkbox'] = "";
|
||||
foreach ($this->m_aEditableFields as $sFieldCode)
|
||||
{
|
||||
foreach ($this->m_aEditableFields as $sFieldCode) {
|
||||
$sDisplayValue = $linkObjOrId->GetEditValue($sFieldCode);
|
||||
$aRow[$sFieldCode] = $sDisplayValue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$aRow['form::checkbox'] = "<input class=\"selection\" data-remote-id=\"$iRemoteObjKey\" data-link-id=\"$iKey\" data-unique-id=\"$iUniqueId\" type=\"checkbox\" onClick=\"oWidget".$this->m_iInputId.".OnSelectChange();\" value=\"$iKey\">";
|
||||
foreach ($this->m_aEditableFields as $sFieldCode)
|
||||
{
|
||||
foreach ($this->m_aEditableFields as $sFieldCode) {
|
||||
$sSafeFieldId = $this->GetFieldId($linkObjOrId->GetKey(), $sFieldCode);
|
||||
$this->AddRowForFieldCode($aRow, $sFieldCode, $aArgs, $linkObjOrId, $oP, $sNameSuffix, $sSafeFieldId);
|
||||
$aFieldsMap[$sFieldCode] = $sSafeFieldId;
|
||||
|
||||
if ($bModified) {
|
||||
$oP->add_ready_script(
|
||||
<<<EOF
|
||||
oWidget{$this->m_iInputId}.AddModified($iUniqueId, {$this->m_iInputId}, $sFieldCode, {$linkObjOrId->Get($sFieldCode)});
|
||||
EOF
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$sState = $linkObjOrId->GetState();
|
||||
$sRemoteKeySafeFieldId = $this->GetFieldId($aArgs['this']->GetKey(), $this->m_sExtKeyToRemote);;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// form for creating a new record
|
||||
if (is_object($linkObjOrId))
|
||||
{
|
||||
if (is_object($linkObjOrId)) {
|
||||
// New link existing only in memory
|
||||
$oNewLinkObj = $linkObjOrId;
|
||||
$iRemoteObjKey = $oNewLinkObj->Get($this->m_sExtKeyToRemote);
|
||||
$oNewLinkObj->Set($this->m_sExtKeyToMe,
|
||||
$oCurrentObj); // Setting the extkey with the object also fills the related external fields
|
||||
}
|
||||
else
|
||||
{
|
||||
$oNewLinkObj->Set($this->m_sExtKeyToMe, $oCurrentObj); // Setting the extkey with the object also fills the related external fields
|
||||
} else {
|
||||
$iRemoteObjKey = $linkObjOrId;
|
||||
$oNewLinkObj = MetaModel::NewObject($this->m_sLinkedClass);
|
||||
$oRemoteObj = MetaModel::GetObject($this->m_sRemoteClass, $iRemoteObjKey);
|
||||
$oNewLinkObj->Set($this->m_sExtKeyToRemote,
|
||||
$oRemoteObj); // Setting the extkey with the object alsoo fills the related external fields
|
||||
$oNewLinkObj->Set($this->m_sExtKeyToMe,
|
||||
$oCurrentObj); // Setting the extkey with the object also fills the related external fields
|
||||
$oNewLinkObj->Set($this->m_sExtKeyToRemote, $oRemoteObj); // Setting the extkey with the object alsoo fills the related external fields
|
||||
$oNewLinkObj->Set($this->m_sExtKeyToMe, $oCurrentObj); // Setting the extkey with the object also fills the related external fields
|
||||
}
|
||||
$sPrefix .= "[-$iUniqueId][";
|
||||
$sNameSuffix = "]"; // To make a tabular form
|
||||
@@ -177,8 +171,7 @@ class UILinksWidget
|
||||
$sInputValue = $iUniqueId > 0 ? "-$iUniqueId" : "$iUniqueId";
|
||||
$aRow['form::checkbox'] = "<input class=\"selection\" data-remote-id=\"$iRemoteObjKey\" data-link-id=\"0\" data-unique-id=\"$iUniqueId\" type=\"checkbox\" onClick=\"oWidget".$this->m_iInputId.".OnSelectChange();\" value=\"$sInputValue\">";
|
||||
|
||||
if ($iUniqueId > 0)
|
||||
{
|
||||
if ($iUniqueId > 0) {
|
||||
// Rows created with ajax call need OnLinkAdded call.
|
||||
//
|
||||
$oP->add_ready_script(
|
||||
@@ -187,9 +180,7 @@ PrepareWidgets();
|
||||
oWidget{$this->m_iInputId}.OnLinkAdded($iUniqueId, $iRemoteObjKey);
|
||||
EOF
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// Rows added before loading the form don't have to call OnLinkAdded.
|
||||
// Listeners are already present and DOM is not recreated
|
||||
$iPositiveUniqueId = -$iUniqueId;
|
||||
@@ -378,10 +369,17 @@ JS
|
||||
$iMaxAddedId = 0;
|
||||
$iAddedId = -1; // Unique id for new links
|
||||
$oBlock->aRemoved = json_decode(utils::ReadPostedParam("attr_{$sFormPrefix}{$this->m_sAttCode}_tbd", '[]', 'raw_data'));
|
||||
$oModified = $oValue->GetModified($this->m_sExtKeyToRemote);
|
||||
while ($oCurrentLink = $oValue->Fetch()) {
|
||||
// We try to retrieve the remote object as usual
|
||||
if (!in_array($oCurrentLink->GetKey(), $oBlock->aRemoved)) {
|
||||
$oLinkedObj = MetaModel::GetObject($this->m_sRemoteClass, $oCurrentLink->Get($this->m_sExtKeyToRemote), false /* Must not be found */);
|
||||
$bModified = false;
|
||||
if (array_key_exists($oCurrentLink->GetKey(), $oModified)) {
|
||||
$oLinkedObj = MetaModel::GetObject($this->m_sRemoteClass, $oModified[$oCurrentLink->GetKey()], false /* Must not be found */);
|
||||
$bModified = true;
|
||||
} else {
|
||||
$oLinkedObj = MetaModel::GetObject($this->m_sRemoteClass, $oCurrentLink->Get($this->m_sExtKeyToRemote), false /* Must not be found */);
|
||||
}
|
||||
// If successful, it means that we can edit its link
|
||||
if ($oLinkedObj !== null) {
|
||||
$bReadOnly = false;
|
||||
@@ -398,11 +396,12 @@ JS
|
||||
}
|
||||
|
||||
$iMaxAddedId = max($iMaxAddedId, $key);
|
||||
$aForm[$key] = $this->GetFormRow($oPage, $oLinkedObj, $oCurrentLink, $aArgs, $oCurrentObj, $key, $bReadOnly);
|
||||
$aForm[$key] = $this->GetFormRow($oPage, $oLinkedObj, $oCurrentLink, $aArgs, $oCurrentObj, $key, $bReadOnly, $bModified);
|
||||
}
|
||||
}
|
||||
$oBlock->iMaxAddedId = (int)$iMaxAddedId;
|
||||
|
||||
|
||||
$oDataTable = DataTableUIBlockFactory::MakeForForm("{$this->m_sAttCode}{$this->m_sNameSuffix}", $this->m_aTableConfig, $aForm);
|
||||
$oDataTable->SetOptions(['select_mode' => 'custom', 'disable_hyperlinks' => true]);
|
||||
$oBlock->AddSubBlock($oDataTable);
|
||||
|
||||
@@ -2095,15 +2095,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;
|
||||
}
|
||||
@@ -2114,32 +2112,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));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2238,20 +2236,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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3176,8 +3195,7 @@ abstract class DBObject implements iDisplay
|
||||
// Freeze the changes at this point
|
||||
$this->InitPreviousValuesForUpdatedAttributes();
|
||||
$aChanges = $this->ListChanges();
|
||||
if (count($aChanges) == 0)
|
||||
{
|
||||
if (count($aChanges) == 0) {
|
||||
// Attempting to update an unchanged object
|
||||
MetaModel::StopReentranceProtection(Metamodel::REENTRANCE_TYPE_UPDATE, $this);
|
||||
IssueLog::Debug("CRUD: DBUpdate $sClass::$sKey Aborted (no change)", LogChannels::DM_CRUD);
|
||||
@@ -3281,8 +3299,7 @@ abstract class DBObject implements iDisplay
|
||||
}
|
||||
|
||||
// Update scalar attributes
|
||||
if (count($aDBChanges) != 0)
|
||||
{
|
||||
if (count($aDBChanges) != 0) {
|
||||
$oFilter = new DBObjectSearch($sClass);
|
||||
$oFilter->AddCondition('id', $this->m_iKey, '=');
|
||||
$oFilter->AllowAllData();
|
||||
|
||||
@@ -608,16 +608,32 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
|
||||
$aAdded = $this->aAdded;
|
||||
$aModified = $this->aModified;
|
||||
$aRemoved = array();
|
||||
if (count($this->aRemoved) > 0)
|
||||
{
|
||||
if (count($this->aRemoved) > 0) {
|
||||
$oSearch = new DBObjectSearch($this->sClass);
|
||||
$oSearch->AddCondition('id', $this->aRemoved, 'IN');
|
||||
$oSet = new DBObjectSet($oSearch);
|
||||
$aRemoved = $oSet->ToArray();
|
||||
}
|
||||
|
||||
return array_merge($aAdded, $aModified, $aRemoved);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of all modified (added, modified and removed) links
|
||||
*
|
||||
* @return array of link objects
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function GetModified($sExtKeyToMe)
|
||||
{
|
||||
$aModified = [];
|
||||
foreach ($this->aModified as $oObj) {
|
||||
$aModified[$oObj->GetKey()] = $oObj->Get($sExtKeyToMe);
|
||||
}
|
||||
|
||||
return $aModified;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DBObject $oHostObject
|
||||
*
|
||||
@@ -661,8 +677,7 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
|
||||
{
|
||||
$aCheckLinks[] = $iLinkId;
|
||||
}
|
||||
foreach ($this->aModified as $iLinkId => $oLink)
|
||||
{
|
||||
foreach ($this->aModified as $iLinkId => $oLink) {
|
||||
$aCheckLinks[] = $oLink->GetKey();
|
||||
}
|
||||
|
||||
@@ -698,8 +713,7 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
|
||||
|
||||
// Write the links according to the existing links
|
||||
//
|
||||
foreach ($this->aAdded as $oLink)
|
||||
{
|
||||
foreach ($this->aAdded as $oLink) {
|
||||
// Make sure that the objects in the set point to "this"
|
||||
$oLink->Set($sExtKeyToMe, $oHostObject->GetKey());
|
||||
|
||||
|
||||
@@ -385,12 +385,10 @@ function LinksWidget(id, sClass, sAttCode, iInputId, sSuffix, bDuplicates, oWizH
|
||||
*/
|
||||
this.OnValueChange = function (iLink, iUniqueId, sAttCode, value, $oSourceObject) {
|
||||
let sFormPrefix = me.iInputId;
|
||||
if (iLink > 0)
|
||||
{
|
||||
if (iLink > 0) {
|
||||
// Modifying an existing link
|
||||
let oModified = me.aModified[iLink];
|
||||
if (oModified == undefined)
|
||||
{
|
||||
if (oModified == undefined) {
|
||||
// Still not marked as modified
|
||||
oModified = {};
|
||||
oModified['formPrefix'] = sFormPrefix;
|
||||
@@ -398,17 +396,26 @@ function LinksWidget(id, sClass, sAttCode, iInputId, sSuffix, bDuplicates, oWizH
|
||||
// Weird formatting, aligned with the output of the direct links widget (new links to be created)
|
||||
oModified['attr_'+sFormPrefix+sAttCode] = value;
|
||||
me.aModified[iLink] = oModified;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// Modifying a newly added link - the structure should already be up to date
|
||||
if (iUniqueId < 0)
|
||||
{
|
||||
if (iUniqueId < 0) {
|
||||
iUniqueId = -iUniqueId;
|
||||
}
|
||||
me.aAdded[iUniqueId]['attr_'+sFormPrefix+sAttCode] = value;
|
||||
}
|
||||
};
|
||||
this.AddModified = function (iLink, sFormPrefix, sAttCode, value) {
|
||||
// Modifying an existing link
|
||||
let oModified = me.aModified[iLink];
|
||||
if (oModified == undefined) {
|
||||
// Still not marked as modified
|
||||
oModified = {};
|
||||
oModified['formPrefix'] = sFormPrefix;
|
||||
}
|
||||
// Weird formatting, aligned with the output of the direct links widget (new links to be created)
|
||||
oModified['attr_'+sFormPrefix+sAttCode] = value;
|
||||
me.aModified[iLink] = oModified;
|
||||
};
|
||||
|
||||
this.OnFormSubmit = function () {
|
||||
let oDiv = $('#linkedset_'+me.id);
|
||||
|
||||
Reference in New Issue
Block a user