mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-13 23:44:11 +01:00
Compare commits
9 Commits
saas-1.0.1
...
support/1.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7ea76869f4 | ||
|
|
8fe5450d9e | ||
|
|
b732673b65 | ||
|
|
05c709056b | ||
|
|
8e7f629923 | ||
|
|
92b3434954 | ||
|
|
71d3a9e443 | ||
|
|
f6aeeb0aaa | ||
|
|
48ab6cb737 |
@@ -1862,7 +1862,7 @@ EOF
|
||||
return $aDetails;
|
||||
}
|
||||
|
||||
protected static function FlattenZList($aList)
|
||||
public static function FlattenZList($aList)
|
||||
{
|
||||
$aResult = array();
|
||||
foreach($aList as $value)
|
||||
@@ -2069,59 +2069,34 @@ EOF
|
||||
/**
|
||||
* Updates the object from the POSTed parameters
|
||||
*/
|
||||
public function UpdateObject($sFormPrefix = '')
|
||||
public function UpdateObject($sFormPrefix = '', $aAttList = null)
|
||||
{
|
||||
$aErrors = array();
|
||||
foreach(MetaModel::ListAttributeDefs(get_class($this)) as $sAttCode=>$oAttDef)
|
||||
if (!is_array($aAttList))
|
||||
{
|
||||
if ($oAttDef->IsLinkSet() && $oAttDef->IsIndirect())
|
||||
{
|
||||
$aLinks = utils::ReadPostedParam("attr_{$sFormPrefix}{$sAttCode}", null);
|
||||
if (is_null($aLinks)) continue;
|
||||
|
||||
$sLinkedClass = $oAttDef->GetLinkedClass();
|
||||
$sExtKeyToRemote = $oAttDef->GetExtKeyToRemote();
|
||||
$sExtKeyToMe = $oAttDef->GetExtKeyToMe();
|
||||
$oLinkedSet = DBObjectSet::FromScratch($sLinkedClass);
|
||||
if (is_array($aLinks))
|
||||
{
|
||||
foreach($aLinks as $id => $aData)
|
||||
{
|
||||
if (is_numeric($id))
|
||||
{
|
||||
if ($id < 0)
|
||||
{
|
||||
// New link to be created, the opposite of the id (-$id) is the ID of the remote object
|
||||
$oLink = MetaModel::NewObject($sLinkedClass);
|
||||
$oLink->Set($sExtKeyToRemote, -$id);
|
||||
$oLink->Set($sExtKeyToMe, $this->GetKey());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Existing link, potentially to be updated...
|
||||
$oLink = MetaModel::GetObject($sLinkedClass, $id);
|
||||
}
|
||||
// Now populate the attributes
|
||||
foreach($aData as $sName => $value)
|
||||
{
|
||||
if (MetaModel::IsValidAttCode($sLinkedClass, $sName))
|
||||
{
|
||||
$oLinkAttDef = MetaModel::GetAttributeDef($sLinkedClass, $sName);
|
||||
if ($oLinkAttDef->IsWritable())
|
||||
{
|
||||
$oLink->Set($sName, $value);
|
||||
}
|
||||
}
|
||||
}
|
||||
$oLinkedSet->AddObject($oLink);
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->Set($sAttCode, $oLinkedSet);
|
||||
}
|
||||
else if ($oAttDef->IsWritable())
|
||||
$aAttList = $this->FlattenZList(MetaModel::GetZListItems(get_class($this), 'details'));
|
||||
// Special case to process the case log, if any...
|
||||
// WARNING: if you change this also check the functions DisplayModifyForm and DisplayCaseLog
|
||||
foreach(MetaModel::ListAttributeDefs(get_class($this)) as $sAttCode => $oAttDef)
|
||||
{
|
||||
$iFlags = $this->GetAttributeFlags($sAttCode);
|
||||
if ($oAttDef instanceof AttributeCaseLog)
|
||||
{
|
||||
if (!($iFlags & (OPT_ATT_HIDDEN|OPT_ATT_SLAVE|OPT_ATT_READONLY)))
|
||||
{
|
||||
// The case log is editable, append it to the list of fields to retrieve
|
||||
$aAttList[] = $sAttCode;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach($aAttList as $sAttCode)
|
||||
{
|
||||
$oAttDef = MetaModel::GetAttributeDef(get_class($this), $sAttCode);
|
||||
|
||||
$iFlags = $this->GetAttributeFlags($sAttCode);
|
||||
if ($oAttDef->IsWritable())
|
||||
{
|
||||
if ( $iFlags & (OPT_ATT_HIDDEN | OPT_ATT_READONLY))
|
||||
{
|
||||
// Non-visible, or read-only attribute, do nothing
|
||||
@@ -2134,6 +2109,49 @@ EOF
|
||||
$aErrors[] = Dict::Format('UI:AttemptingToSetASlaveAttribute_Name', $oAttDef->GetLabel());
|
||||
}
|
||||
}
|
||||
elseif ($oAttDef->IsLinkSet() && $oAttDef->IsIndirect())
|
||||
{
|
||||
$aLinks = utils::ReadPostedParam("attr_{$sFormPrefix}{$sAttCode}", null);
|
||||
$sLinkedClass = $oAttDef->GetLinkedClass();
|
||||
$sExtKeyToRemote = $oAttDef->GetExtKeyToRemote();
|
||||
$sExtKeyToMe = $oAttDef->GetExtKeyToMe();
|
||||
$oLinkedSet = DBObjectSet::FromScratch($sLinkedClass);
|
||||
if (is_array($aLinks))
|
||||
{
|
||||
foreach($aLinks as $id => $aData)
|
||||
{
|
||||
if (is_numeric($id))
|
||||
{
|
||||
if ($id < 0)
|
||||
{
|
||||
// New link to be created, the opposite of the id (-$id) is the ID of the remote object
|
||||
$oLink = MetaModel::NewObject($sLinkedClass);
|
||||
$oLink->Set($sExtKeyToRemote, -$id);
|
||||
$oLink->Set($sExtKeyToMe, $this->GetKey());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Existing link, potentially to be updated...
|
||||
$oLink = MetaModel::GetObject($sLinkedClass, $id);
|
||||
}
|
||||
// Now populate the attributes
|
||||
foreach($aData as $sName => $value)
|
||||
{
|
||||
if (MetaModel::IsValidAttCode($sLinkedClass, $sName))
|
||||
{
|
||||
$oLinkAttDef = MetaModel::GetAttributeDef($sLinkedClass, $sName);
|
||||
if ($oLinkAttDef->IsWritable())
|
||||
{
|
||||
$oLink->Set($sName, $value);
|
||||
}
|
||||
}
|
||||
}
|
||||
$oLinkedSet->AddObject($oLink);
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->Set($sAttCode, $oLinkedSet);
|
||||
}
|
||||
elseif ($oAttDef->GetEditClass() == 'Document')
|
||||
{
|
||||
// There should be an uploaded file with the named attr_<attCode>
|
||||
|
||||
@@ -1349,13 +1349,21 @@ class AttributeText extends AttributeString
|
||||
|
||||
static public function RenderWikiHtml($sText)
|
||||
{
|
||||
if (preg_match_all(WIKI_URL, $sText, $aAllMatches, PREG_SET_ORDER))
|
||||
if (preg_match_all(WIKI_URL, $sText, $aAllMatches, PREG_SET_ORDER /* important !*/ |PREG_OFFSET_CAPTURE /* important ! */))
|
||||
{
|
||||
foreach($aAllMatches as $iPos => $aMatches)
|
||||
$aUrls = array();
|
||||
$i = count($aAllMatches);
|
||||
// Replace the URLs by an actual hyperlink <a href="...">...</a>
|
||||
// Let's do it backwards so that the initial positions are not modified by the replacement
|
||||
// This works if the matches are captured: in the order they occur in the string AND
|
||||
// with their offset (i.e. position) inside the string
|
||||
while($i > 0)
|
||||
{
|
||||
$sUrl = $aMatches[0];
|
||||
$sHLink = "<a href=\"$sUrl\">$sUrl</a>";
|
||||
$sText = str_replace($sUrl, $sHLink, $sText);
|
||||
$i--;
|
||||
$sUrl = $aAllMatches[$i][0][0]; // String corresponding to the main pattern
|
||||
$iPos = $aAllMatches[$i][0][1]; // Position of the main pattern
|
||||
$sText = substr_replace($sText, "<a href=\"$sUrl\">$sUrl</a>", $iPos, strlen($sUrl));
|
||||
|
||||
}
|
||||
}
|
||||
if (preg_match_all(WIKI_OBJECT_REGEXP, $sText, $aAllMatches, PREG_SET_ORDER))
|
||||
|
||||
@@ -105,6 +105,34 @@ abstract class TriggerOnObject extends Trigger
|
||||
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
|
||||
}
|
||||
}
|
||||
/**
|
||||
* To trigger notifications when a ticket is updated from the portal
|
||||
*/
|
||||
class TriggerOnPortalUpdate extends TriggerOnObject
|
||||
{
|
||||
public static function Init()
|
||||
{
|
||||
$aParams = array
|
||||
(
|
||||
"category" => "core/cmdb",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => "description",
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => array(),
|
||||
"db_table" => "priv_trigger_onportalupdate",
|
||||
"db_key_field" => "id",
|
||||
"db_finalclass_field" => "",
|
||||
"display_template" => "",
|
||||
);
|
||||
MetaModel::Init_Params($aParams);
|
||||
MetaModel::Init_InheritAttributes();
|
||||
|
||||
// Display lists
|
||||
MetaModel::Init_SetZListItems('details', array('description', 'target_class', 'action_list')); // Attributes to be displayed for the complete details
|
||||
MetaModel::Init_SetZListItems('list', array('finalclass', 'target_class', 'description')); // Attributes to be displayed for a list
|
||||
// Search criteria
|
||||
}
|
||||
}
|
||||
|
||||
abstract class TriggerOnStateChange extends TriggerOnObject
|
||||
{
|
||||
|
||||
@@ -436,6 +436,15 @@ Dict::Add('EN US', 'English', 'English', array(
|
||||
'Class:TriggerOnObject/Attribute:target_class+' => '',
|
||||
));
|
||||
|
||||
//
|
||||
// Class: TriggerOnPortalUpdate
|
||||
//
|
||||
|
||||
Dict::Add('EN US', 'English', 'English', array(
|
||||
'Class:TriggerOnPortalUpdate' => 'Trigger (when updated from the portal)',
|
||||
|
||||
));
|
||||
|
||||
//
|
||||
// Class: TriggerOnStateChange
|
||||
//
|
||||
|
||||
@@ -48,6 +48,8 @@ Dict::Add('FR FR', 'French', 'Français', array(
|
||||
'Class:ActionEmail/Attribute:importance/Value:low+' => '',
|
||||
'Class:ActionEmail/Attribute:importance/Value:normal' => 'Normale',
|
||||
'Class:ActionEmail/Attribute:importance/Value:normal+' => '',
|
||||
'Class:TriggerOnPortalUdpate' => 'Déclencheur sur mise à jour depuis le portail',
|
||||
'Class:TriggerOnPortalUdpate+' => '',
|
||||
'Class:TriggerOnStateEnter' => 'Déclencheur sur un objet entrant dans un état',
|
||||
'Class:TriggerOnStateEnter+' => '',
|
||||
'Class:TriggerOnStateLeave' => 'Déclencheur sur un objet quitant un état',
|
||||
|
||||
23
pages/UI.php
23
pages/UI.php
@@ -920,10 +920,31 @@ EOF
|
||||
$iChangeId = $oMyChange->DBInsert();
|
||||
utils::RemoveTransaction($sTransactionId);
|
||||
}
|
||||
// Explicitely build the list of attributes to update since we do NOT update the linksets
|
||||
// because they are not part of the form
|
||||
$aAttList = cmdbAbstractObject::FlattenZList(MetaModel::GetZListItems($sClass, 'details'));
|
||||
foreach($aAttList as $index => $sAttCode)
|
||||
{
|
||||
$oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
|
||||
if ($oAttDef->IsLinkset())
|
||||
{
|
||||
unset($aAttList[$index]);
|
||||
}
|
||||
}
|
||||
// Special case to process the case log, if any...
|
||||
// WARNING: if you change this also check the functions DisplayModifyForm and DisplayCaseLog
|
||||
foreach(MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef)
|
||||
{
|
||||
if ($oAttDef instanceof AttributeCaseLog)
|
||||
{
|
||||
$aAttList[] = $sAttCode;
|
||||
}
|
||||
}
|
||||
|
||||
foreach($aSelectedObj as $iId)
|
||||
{
|
||||
$oObj = MetaModel::GetObject($sClass, $iId);
|
||||
$aErrors = $oObj->UpdateObject('');
|
||||
$aErrors = $oObj->UpdateObject('', $aAttList);
|
||||
$bResult = (count($aErrors) == 0);
|
||||
if ($bResult)
|
||||
{
|
||||
|
||||
@@ -85,7 +85,7 @@ try
|
||||
{
|
||||
$aValidIds[] = $oObj->GetKey();
|
||||
}
|
||||
$oFilter = $oDefinitionFilter;
|
||||
$oFilter = clone $oDefinitionFilter;
|
||||
$oFilter->AddCondition('id', $aValidIds, 'NOTIN');
|
||||
$oErrorObjectSet = new CMDBObjectSet($oFilter);
|
||||
}
|
||||
|
||||
@@ -907,6 +907,14 @@ function AddComment($oP, $id)
|
||||
$iChangeId = $oMyChange->DBInsert();
|
||||
$oRequest->DBUpdateTracked($oMyChange);
|
||||
$oP->p("<h1>".Dict::Format('UI:Class_Object_Updated', MetaModel::GetName(get_class($oRequest)), $oRequest->GetName())."</h1>\n");
|
||||
|
||||
// If there is any trigger for the Portal Update, then activate them
|
||||
$sOQL = "SELECT TriggerOnPortalUpdate WHERE target_class ='UserRequest'";
|
||||
$oSet = new DBObjectSet(DBObjectSearch::FromOQL($sOQL));
|
||||
while($oTrigger = $oSet->Fetch())
|
||||
{
|
||||
$oTrigger->DoActivate($oRequest->ToArgs('this'));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -456,9 +456,9 @@ EOF
|
||||
return parent::GetAttributeFlags($sAttCode, $aReasons);
|
||||
}
|
||||
|
||||
public function UpdateObject($sFormPrefix = '')
|
||||
public function UpdateObject($sFormPrefix = '', $sAttList = null)
|
||||
{
|
||||
parent::UpdateObject($sFormPrefix);
|
||||
parent::UpdateObject($sFormPrefix, $sAttList);
|
||||
// And now read the other post parameters...
|
||||
$oAttributeSet = $this->Get('attribute_list');
|
||||
$aAttributes = array();
|
||||
@@ -647,6 +647,7 @@ EOF
|
||||
parent::AfterInsert();
|
||||
|
||||
$sTable = $this->GetDataTable();
|
||||
$sReplicaTable = MetaModel::DBGetTable('SynchroReplica');
|
||||
|
||||
$aColumns = $this->GetSQLColumns();
|
||||
|
||||
@@ -669,7 +670,7 @@ EOF
|
||||
$sTriggerInsert = "CREATE TRIGGER `{$sTable}_bi` BEFORE INSERT ON $sTable";
|
||||
$sTriggerInsert .= " FOR EACH ROW";
|
||||
$sTriggerInsert .= " BEGIN";
|
||||
$sTriggerInsert .= " INSERT INTO priv_sync_replica (sync_source_id, status_last_seen, `status`) VALUES ({$this->GetKey()}, NOW(), 'new');";
|
||||
$sTriggerInsert .= " INSERT INTO {$sReplicaTable} (sync_source_id, status_last_seen, `status`) VALUES ({$this->GetKey()}, NOW(), 'new');";
|
||||
$sTriggerInsert .= " SET NEW.id = LAST_INSERT_ID();";
|
||||
$sTriggerInsert .= " END;";
|
||||
CMDBSource::Query($sTriggerInsert);
|
||||
@@ -691,7 +692,7 @@ EOF
|
||||
$sTriggerUpdate .= " FOR EACH ROW";
|
||||
$sTriggerUpdate .= " BEGIN";
|
||||
$sTriggerUpdate .= " IF @itopuser is null THEN";
|
||||
$sTriggerUpdate .= " UPDATE priv_sync_replica SET status_last_seen = NOW(), `status` = IF(`status` = 'obsolete', IF(`dest_id` IS NULL, 'new', 'modified'), IF(`status` IN ('synchronized') AND ($sIsModified), 'modified', `status`)) WHERE sync_source_id = {$this->GetKey()} AND id = OLD.id;";
|
||||
$sTriggerUpdate .= " UPDATE {$sReplicaTable} SET status_last_seen = NOW(), `status` = IF(`status` = 'obsolete', IF(`dest_id` IS NULL, 'new', 'modified'), IF(`status` IN ('synchronized') AND ($sIsModified), 'modified', `status`)) WHERE sync_source_id = {$this->GetKey()} AND id = OLD.id;";
|
||||
$sTriggerUpdate .= " SET NEW.id = OLD.id;"; // make sure this id won't change
|
||||
$sTriggerUpdate .= " END IF;";
|
||||
$sTriggerUpdate .= " END;";
|
||||
@@ -700,7 +701,7 @@ EOF
|
||||
$sTriggerInsert = "CREATE TRIGGER `{$sTable}_ad` AFTER DELETE ON $sTable";
|
||||
$sTriggerInsert .= " FOR EACH ROW";
|
||||
$sTriggerInsert .= " BEGIN";
|
||||
$sTriggerInsert .= " DELETE FROM priv_sync_replica WHERE id = OLD.id;";
|
||||
$sTriggerInsert .= " DELETE FROM {$sReplicaTable} WHERE id = OLD.id;";
|
||||
$sTriggerInsert .= " END;";
|
||||
CMDBSource::Query($sTriggerInsert);
|
||||
}
|
||||
@@ -1299,7 +1300,7 @@ class SynchroLog extends DBObject
|
||||
MetaModel::Init_AddAttribute(new AttributeInteger("stats_nb_obj_new_updated", array("allowed_values"=>null, "sql"=>"stats_nb_obj_new_updated", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeInteger("stats_nb_obj_new_unchanged", array("allowed_values"=>null, "sql"=>"stats_nb_obj_new_unchanged", "default_value"=>0, "is_null_allowed"=>false, "depends_on"=>array())));
|
||||
|
||||
MetaModel::Init_AddAttribute(new AttributeString("last_error", array("allowed_values"=>null, "sql"=>"last_error", "default_value"=>'', "is_null_allowed"=>true, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeText("last_error", array("allowed_values"=>null, "sql"=>"last_error", "default_value"=>'', "is_null_allowed"=>true, "depends_on"=>array())));
|
||||
MetaModel::Init_AddAttribute(new AttributeLongText("traces", array("allowed_values"=>null, "sql"=>"traces", "default_value"=>'', "is_null_allowed"=>true, "depends_on"=>array())));
|
||||
|
||||
// Display lists
|
||||
@@ -1603,7 +1604,7 @@ class SynchroReplica extends DBObject implements iDisplay
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->UpdateObjectFromReplica($oDestObj, $aAttributes, $oChange, $oStatLog, 'stats_nb_obj', 'stats_nb_obj_updated_errors');
|
||||
$this->UpdateObjectFromReplica($oDestObj, $aAttributes, $oChange, $oStatLog, '', 'stats_nb_obj_updated_errors');
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1633,13 +1634,19 @@ class SynchroReplica extends DBObject implements iDisplay
|
||||
{
|
||||
$oDestObj->DBUpdateTracked($oChange);
|
||||
$oStatLog->AddTrace('Updated object - Values: {'.implode(', ', $aValueTrace).'}', $this);
|
||||
$oStatLog->Inc($sStatsCode.'_updated');
|
||||
if ($sStatsCode != '')
|
||||
{
|
||||
$oStatLog->Inc($sStatsCode.'_updated');
|
||||
}
|
||||
$this->Set('info_last_modified', date('Y-m-d H:i:s'));
|
||||
}
|
||||
else
|
||||
{
|
||||
$oStatLog->AddTrace('Unchanged object', $this);
|
||||
$oStatLog->Inc($sStatsCode.'_unchanged');
|
||||
if ($sStatsCode != '')
|
||||
{
|
||||
$oStatLog->Inc($sStatsCode.'_unchanged');
|
||||
}
|
||||
}
|
||||
|
||||
$this->Set('status_last_error', '');
|
||||
|
||||
Reference in New Issue
Block a user