Compare commits

...

9 Commits

Author SHA1 Message Date
Denis Flaven
7ea76869f4 Bug fix: subsequent audit results were wrong when a 'negative' rule was used. Same fix as change [1560] in trunk
SVN:1.1[1649]
2011-10-27 16:43:23 +00:00
Denis Flaven
8fe5450d9e Fixed Trac #492: bulk modify resets the linksets
SVN:1.1[1631]
2011-10-12 19:44:40 +00:00
Denis Flaven
b732673b65 Fix for Trac #434: new class of Trigger: TriggerOnPortalUpdate
SVN:1.1[1442]
2011-08-09 14:46:16 +00:00
Denis Flaven
05c709056b Fixed Trac #433: Incorrect triggers created for the Data Synchro when the iTop uses a prefix for the tables.
SVN:1.1[1373]
2011-07-26 16:49:33 +00:00
Denis Flaven
8e7f629923 - Fixed Trac #429: web browser can crash when a text field contains several times the same URL !!!
SVN:1.1[1338]
2011-07-06 17:13:28 +00:00
Denis Flaven
92b3434954 - Fix for bug #420: error message too long
- Fix for bug #424: error when processing unmodified replicas

SVN:1.1[1331]
2011-07-05 13:27:26 +00:00
Romain Quetiez
71d3a9e443 Fix for #427 implemented into branch 1.1 (delete all team members)
SVN:1.1[1330]
2011-07-05 09:38:04 +00:00
Romain Quetiez
f6aeeb0aaa Branching 1.1 for patching until 1.2 gets released
SVN:1.1[1329]
2011-07-05 09:04:40 +00:00
Romain Quetiez
48ab6cb737 Created tag for release 1.1.0 build 181
SVN:1.1[1266]
2011-05-04 12:30:41 +00:00
9 changed files with 166 additions and 65 deletions

View File

@@ -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>

View File

@@ -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))

View File

@@ -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
{

View File

@@ -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
//

View File

@@ -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',

View File

@@ -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)
{

View File

@@ -85,7 +85,7 @@ try
{
$aValidIds[] = $oObj->GetKey();
}
$oFilter = $oDefinitionFilter;
$oFilter = clone $oDefinitionFilter;
$oFilter->AddCondition('id', $aValidIds, 'NOTIN');
$oErrorObjectSet = new CMDBObjectSet($oFilter);
}

View File

@@ -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
{

View File

@@ -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', '');