- Fixed bug with change tracking of TEXT attributes

- Log any email notification (successful or not)
- Class selection always made through a Combo box
- Automatic creation of indexes for external keys
- New trigger: on object creation
- Application log: added a status string
- Added documentation to the WSDL (+ anyType replaced by string)
- SOAP: improved handling of enumeration attributes
- SOAP: returned logs to mention the name of the parameter as advertised in the WSDL file (different than the name of the attribute in Itop)
- Finalized SOAP tests
- Added a SOAP client example

SVN:trunk[246]
This commit is contained in:
Romain Quetiez
2010-01-13 13:30:08 +00:00
parent 89fa70d755
commit 8964b13a2e
16 changed files with 554 additions and 117 deletions

View File

@@ -307,7 +307,7 @@ class URP_Dimensions extends UserRightsBaseClass
//MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeString("name", array("label"=>"Name", "description"=>"label", "allowed_values"=>null, "sql"=>"name", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("description", array("label"=>"Description", "description"=>"one line description", "allowed_values"=>null, "sql"=>"description", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("type", array("label"=>"Type", "description"=>"class name or data type (projection unit)", "allowed_values"=>new ValueSetEnumClasses('bizmodel', 'String,Integer'), "sql"=>"type", "default_value"=>'String', "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeClass("type", array("label"=>"Type", "description"=>"class name or data type (projection unit)", "class_category"=>"bizmodel", "more_values"=>"String,Integer", "sql"=>"type", "default_value"=>'String', "is_null_allowed"=>false, "depends_on"=>array())));
//MetaModel::Init_InheritFilters();
MetaModel::Init_AddFilterFromAttribute("name");

View File

@@ -31,7 +31,7 @@ class InputOutputTask extends cmdbAbstractObject
MetaModel::Init_AddAttribute(new AttributeEnum("source_type", array("label"=>"Source Type", "description"=>"Type of data source", "allowed_values"=>new ValueSetEnum('File, Database, Web Service'), "sql"=>"source_type", "default_value"=>"File", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeEnum("source_subtype", array("label"=>"Source Subtype", "description"=>"Subtype of Data Source", "allowed_values"=>new ValueSetEnum('Oracle, MySQL, Postgress, MSSQL, SOAP, HTTP-Get, HTTP-Post, XML/RPC, CSV, XML, Excel'), "sql"=>"source_subtype", "default_value"=>"CSV", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("source_path", array("label"=>"Source Path", "description"=>"Path to the icon o the menu", "allowed_values"=>null, "sql"=>"source_path", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeEnum("objects_class", array("label"=>"Objects Class", "description"=>"Class of the objects processed by this task", "allowed_values"=>new ValueSetEnumClasses(), "sql"=>"objects_class", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeClass("objects_class", array("label"=>"Objects Class", "description"=>"Class of the objects processed by this task", "class_category"=>"", "more_values"=>"", "sql"=>"objects_class", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeEnum("test_mode", array("label"=>"Test Mode", "description"=>"If set to 'Yes' the modifications are not applied", "allowed_values"=>new ValueSetEnum('Yes,No'), "sql"=>"test_mode", "default_value"=>'No', "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeEnum("verbose_mode", array("label"=>"Verbose Mode", "description"=>"If set to 'Yes' extra debug information is added to the log", "allowed_values"=>new ValueSetEnum('Yes,No'), "sql"=>"verbose_mode", "default_value" => 'No', "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeEnum("options", array("label"=>"Options", "description"=>"Reconciliation options", "allowed_values"=>new ValueSetEnum('Full, Update Only, Creation Only'), "sql"=>"options", "default_value"=> 'Full', "is_null_allowed"=>true, "depends_on"=>array())));

View File

@@ -215,25 +215,28 @@ class ActionEmail extends ActionNotification
$sHeaders .= "Bcc: $sBCC\r\n";
}
// Mail it
$oLog = new EventNotificationEmail();
if (mail($sTo, $sSubject, $sBody, $sHeaders))
{
$oLog = new EventNotificationEmail();
$oLog->Set('userinfo', UserRights::GetUser());
$oLog->Set('trigger_id', $oTrigger->GetKey());
$oLog->Set('action_id', $this->GetKey());
$oLog->Set('object_id', $aContextArgs['this->id']);
$oLog->Set('to', $sTo);
$oLog->Set('cc', $sCC);
$oLog->Set('bcc', $sBCC);
$oLog->Set('subject', $sSubject);
$oLog->Set('body', $sBody);
$oLog->DBInsertNoReload();
$oLog->Set('message', 'Notification sent');
}
else
{
throw new CoreException('mail not sent', array('action'=>$this->GetKey(), 'to'=>$sTo, 'subject'=>$sSubject, 'headers'=>$sHeaders));
$aLastError = error_get_last();
$oLog->Set('message', 'Mail could not be sent: '.$aLastError['message']);
//throw new CoreException('mail not sent', array('action'=>$this->GetKey(), 'to'=>$sTo, 'subject'=>$sSubject, 'headers'=>$sHeaders));
}
$oLog->Set('userinfo', UserRights::GetUser());
$oLog->Set('trigger_id', $oTrigger->GetKey());
$oLog->Set('action_id', $this->GetKey());
$oLog->Set('object_id', $aContextArgs['this->id']);
$oLog->Set('to', $sTo);
$oLog->Set('cc', $sCC);
$oLog->Set('bcc', $sBCC);
$oLog->Set('subject', $sSubject);
$oLog->Set('body', $sBody);
$oLog->DBInsertNoReload();
}
}
?>

View File

@@ -600,6 +600,30 @@ class AttributeString extends AttributeDBField
}
}
/**
* An attibute that matches an object class
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version $itopversion$
*/
class AttributeClass extends AttributeString
{
static protected function ListExpectedParams()
{
return array_merge(parent::ListExpectedParams(), array("class_category", "more_values"));
}
public function __construct($sCode, $aParams)
{
$this->m_sCode = $sCode;
$aParams["allowed_values"] = new ValueSetEnumClasses($aParams['class_category'], $aParams['more_values']);
parent::__construct($sCode, $aParams);
}
}
/**
* Map a varchar column (size < ?) to an attribute that must never be shown to the user

View File

@@ -304,8 +304,8 @@ class CMDBChangeOpSetAttributeBlob extends CMDBChangeOpSetAttribute
$aParams = array
(
"category" => "core/cmdb",
"name" => "object data change",
"description" => "Object data change tracking",
"name" => "data change",
"description" => "data change tracking",
"key_type" => "",
"key_label" => "",
"name_attcode" => "change",
@@ -357,5 +357,71 @@ class CMDBChangeOpSetAttributeBlob extends CMDBChangeOpSetAttribute
}
}
/**
* Record the modification of a multiline string (text)
*
* @package iTopORM
* @author Romain Quetiez <romainquetiez@yahoo.fr>
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.itop.com
* @since 1.0
* @version $itopversion$
*/
class CMDBChangeOpSetAttributeText extends CMDBChangeOpSetAttribute
{
public static function Init()
{
$aParams = array
(
"category" => "core/cmdb",
"name" => "text change",
"description" => "text change tracking",
"key_type" => "",
"key_label" => "",
"name_attcode" => "change",
"state_attcode" => "",
"reconc_keys" => array(),
"db_table" => "priv_changeop_setatt_text",
"db_key_field" => "id",
"db_finalclass_field" => "",
);
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeText("prevdata", array("label"=>"Previous data", "description"=>"previous contents of the attribute", "allowed_values"=>null, "sql"=>"prevdata", "default_value"=>"", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_InheritFilters();
// Display lists
MetaModel::Init_SetZListItems('details', array('date', 'userinfo', 'attcode')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('date', 'userinfo', 'attcode')); // Attributes to be displayed for a list
}
/**
* Describe (as a text string) the modifications corresponding to this change
*/
public function GetDescription()
{
// Temporary, until we change the options of GetDescription() -needs a more global revision
$bIsHtml = true;
$sResult = '';
$oTargetObjectClass = $this->Get('objclass');
$oTargetObjectKey = $this->Get('objkey');
$oTargetSearch = new DBObjectSearch($oTargetObjectClass);
$oTargetSearch->AddCondition('id', $oTargetObjectKey);
$oMonoObjectSet = new DBObjectSet($oTargetSearch);
if (UserRights::IsActionAllowedOnAttribute($this->Get('objclass'), $this->Get('attcode'), UR_ACTION_READ, $oMonoObjectSet) == UR_ALLOWED_YES)
{
$oAttDef = MetaModel::GetAttributeDef($this->Get('objclass'), $this->Get('attcode'));
$sAttName = $oAttDef->GetLabel();
$sTextView = '<div>'.$this->GetAsHtml('prevdata').'</div>';
//$sDocView = $oPrevDoc->GetDisplayInline(get_class($this), $this->GetKey(), 'prevdata');
$sResult = "$sAttName changed, previous value: $sTextView";
}
return $sResult;
}
}
?>

View File

@@ -193,6 +193,26 @@ abstract class CMDBObject extends DBObject
$oMyChangeOp->Set("prevdata", $original);
$iId = $oMyChangeOp->DBInsertNoReload();
}
elseif ($oAttDef instanceOf AttributeText)
{
// Data blobs
$oMyChangeOp = MetaModel::NewObject("CMDBChangeOpSetAttributeText");
$oMyChangeOp->Set("change", $oChange->GetKey());
$oMyChangeOp->Set("objclass", get_class($this));
$oMyChangeOp->Set("objkey", $this->GetKey());
$oMyChangeOp->Set("attcode", $sAttCode);
if (array_key_exists($sAttCode, $aOrigValues))
{
$original = $aOrigValues[$sAttCode];
}
else
{
$original = null;
}
$oMyChangeOp->Set("prevdata", $original);
$iId = $oMyChangeOp->DBInsertNoReload();
}
else
{
// Scalars

View File

@@ -342,6 +342,16 @@ class CMDBSource
return (strtolower($aFieldData["Null"]) == "yes");
}
public static function HasIndex($sTable, $sField)
{
$aTableInfo = self::GetTableInfo($sTable);
if (empty($aTableInfo)) return false;
if (!array_key_exists($sField, $aTableInfo["Fields"])) return false;
$aFieldData = $aTableInfo["Fields"][$sField];
// $aFieldData could be 'PRI' for the primary key, or 'MUL', or ?
return (strlen($aFieldData["Key"]) > 0);
}
// Returns an array of (fieldname => array of field info)
public static function GetTableFieldsList($sTable)
{

View File

@@ -497,6 +497,17 @@ abstract class DBObject
}
}
}
elseif ($oAtt->IsWritable() && $oAtt->IsScalar())
{
$aValues = $oAtt->GetAllowedValues();
if (count($aValues) > 0)
{
if (!array_key_exists($toCheck, $aValues))
{
return false;
}
}
}
return true;
}
@@ -690,9 +701,19 @@ abstract class DBObject
}
$this->DBWriteLinks();
// Reload to update the external attributes
$this->m_bIsInDB = true;
// Activate any existing trigger
$sClass = get_class($this);
$oSet = new DBObjectSet(new DBObjectSearch('TriggerOnObjectCreate'));
while ($oTrigger = $oSet->Fetch())
{
if (MetaModel::IsParentClass($oTrigger->Get('target_class'), $sClass))
{
$oTrigger->DoActivate($this->ToArgs('this'));
}
}
return $this->m_iKey;
}
@@ -849,6 +870,8 @@ abstract class DBObject
$aScalarArgs = array();
$aScalarArgs[$sArgName] = $this->GetKey();
$aScalarArgs[$sArgName.'->id'] = $this->GetKey();
$aScalarArgs[$sArgName.'->hyperlink()'] = $this->GetHyperlink();
$aScalarArgs[$sArgName.'->name()'] = $this->GetName();
$sClass = get_class($this);
foreach(MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef)

View File

@@ -32,15 +32,17 @@ class Event extends cmdbAbstractObject
);
MetaModel::Init_Params($aParams);
//MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeString("message", array("label"=>"message", "description"=>"short description of the event", "allowed_values"=>null, "sql"=>"message", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeDate("date", array("label"=>"date", "description"=>"date and time at which the changes have been recorded", "allowed_values"=>null, "sql"=>"date", "default_value"=>"", "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("userinfo", array("label"=>"user info", "description"=>"identification of the user that was doing the action that triggered this event", "allowed_values"=>null, "sql"=>"userinfo", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
//MetaModel::Init_InheritFilters();
MetaModel::Init_AddFilterFromAttribute("message");
MetaModel::Init_AddFilterFromAttribute("date");
// Display lists
MetaModel::Init_SetZListItems('details', array('finalclass', 'date', 'userinfo')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('finalclass', 'date')); // Attributes to be displayed for a list
MetaModel::Init_SetZListItems('details', array('message', 'date', 'userinfo')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('date', 'finalclass', 'message')); // Attributes to be displayed for a list
// Search criteria
// MetaModel::Init_SetZListItems('standard_search', array('name')); // Criteria of the std search form
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form

View File

@@ -2092,18 +2092,30 @@ abstract class MetaModel
{
$aErrors[$sClass][] = "field '$sField' could not be found in table '$sTable'";
$aSugFix[$sClass][] = "ALTER TABLE `$sTable` ADD `$sField` $sFieldSpecs";
}
elseif ($oAttDef->IsNullAllowed() != CMDBSource::IsNullAllowed($sTable, $sField))
{
if ($oAttDef->IsNullAllowed())
if ($oAttDef->IsExternalKey())
{
$aErrors[$sClass][] = "field '$sField' in table '$sTable' could be NULL";
$aSugFix[$sClass][] = "ALTER TABLE `$sTable` CHANGE `$sField` `$sField` $sFieldSpecs";
$aSugFix[$sClass][] = "ALTER TABLE `$sTable` ADD INDEX (`$sField`)";
}
else
}
else
{
if ($oAttDef->IsNullAllowed() != CMDBSource::IsNullAllowed($sTable, $sField))
{
$aErrors[$sClass][] = "field '$sField' in table '$sTable' could NOT be NULL";
$aSugFix[$sClass][] = "ALTER TABLE `$sTable` CHANGE `$sField` `$sField` $sFieldSpecs";
if ($oAttDef->IsNullAllowed())
{
$aErrors[$sClass][] = "field '$sField' in table '$sTable' could be NULL";
$aSugFix[$sClass][] = "ALTER TABLE `$sTable` CHANGE `$sField` `$sField` $sFieldSpecs";
}
else
{
$aErrors[$sClass][] = "field '$sField' in table '$sTable' could NOT be NULL";
$aSugFix[$sClass][] = "ALTER TABLE `$sTable` CHANGE `$sField` `$sField` $sFieldSpecs";
}
}
if ($oAttDef->IsExternalKey() && !CMDBSource::HasIndex($sTable, $sField))
{
$aErrors[$sClass][] = "Foreign key '$sField' in table '$sTable' should have an index";
$aSugFix[$sClass][] = "ALTER TABLE `$sTable` ADD INDEX (`$sField`)";
}
}
}

View File

@@ -82,7 +82,7 @@ class TriggerOnStateChange extends Trigger
);
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeString("target_class", array("label"=>"Target class", "description"=>"label", "allowed_values"=>null, "sql"=>"target_class", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeClass("target_class", array("label"=>"Target class", "description"=>"label", "class_category"=>"bizmodel", "more_values"=>null, "sql"=>"target_class", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("state", array("label"=>"State", "description"=>"label", "allowed_values"=>null, "sql"=>"state", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_InheritFilters();
@@ -96,7 +96,6 @@ class TriggerOnStateChange extends Trigger
// MetaModel::Init_SetZListItems('standard_search', array('name')); // Criteria of the std search form
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
}
}
class TriggerOnStateEnter extends TriggerOnStateChange
@@ -165,6 +164,41 @@ class TriggerOnStateLeave extends TriggerOnStateChange
}
}
class TriggerOnObjectCreate extends Trigger
{
public static function Init()
{
$aParams = array
(
"category" => "core/cmdb",
"name" => "Trigger on object creation",
"description" => "Trigger on object creation of [a child class of] the given class",
"key_type" => "autoincrement",
"key_label" => "",
"name_attcode" => "",
"state_attcode" => "",
"reconc_keys" => array(),
"db_table" => "priv_trigger_onobjcreate",
"db_key_field" => "id",
"db_finalclass_field" => "",
"display_template" => "",
);
MetaModel::Init_Params($aParams);
MetaModel::Init_InheritAttributes();
MetaModel::Init_AddAttribute(new AttributeClass("target_class", array("label"=>"Target class", "description"=>"label", "class_category"=>"bizmodel", "more_values"=>null, "sql"=>"target_class", "default_value"=>null, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_InheritFilters();
MetaModel::Init_AddFilterFromAttribute("target_class");
// Display lists
MetaModel::Init_SetZListItems('details', array('description', 'target_class')); // Attributes to be displayed for the complete details
MetaModel::Init_SetZListItems('list', array('finalclass', 'target_class')); // Attributes to be displayed for a list
// Search criteria
// MetaModel::Init_SetZListItems('standard_search', array('name')); // Criteria of the std search form
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
}
}
class lnkTriggerAction extends cmdbAbstractObject
{
public static function Init()

View File

@@ -128,16 +128,23 @@ class ValueSetObjects extends ValueSetDefinition
*/
class ValueSetEnum extends ValueSetDefinition
{
protected $m_values;
public function __construct($Values)
{
if (is_array($Values))
$this->m_values = $Values;
}
protected function LoadValues($aArgs)
{
if (is_array($this->m_values))
{
$aValues = $Values;
$aValues = $this->m_values;
}
else
{
$aValues = array();
foreach (explode(",", $Values) as $sVal)
foreach (explode(",", $this->m_values) as $sVal)
{
$sVal = trim($sVal);
$sKey = $sVal;
@@ -145,10 +152,6 @@ class ValueSetEnum extends ValueSetDefinition
}
}
$this->m_aValues = $aValues;
}
protected function LoadValues($aArgs)
{
return true;
}
}
@@ -166,20 +169,25 @@ class ValueSetEnum extends ValueSetDefinition
*/
class ValueSetEnumClasses extends ValueSetEnum
{
public function __construct($sCategory = '', $sAdditionalValues = '')
{
// First, build it from the series of additional values
parent::__construct($sAdditionalValues);
protected $m_sCategories;
// Second: add the list of classes
foreach (MetaModel::GetClasses($sCategory) as $sClass)
{
$this->m_aValues[$sClass] = MetaModel::GetName($sClass);
}
public function __construct($sCategories = '', $sAdditionalValues = '')
{
$this->m_sCategories = $sCategories;
parent::__construct($sAdditionalValues);
}
protected function LoadValues($aArgs)
{
{
// First, get the additional values
parent::LoadValues($aArgs);
// Then, add the classes from the category definition
foreach (MetaModel::GetClasses($this->m_sCategories) as $sClass)
{
$this->m_aValues[$sClass] = MetaModel::GetName($sClass);
}
return true;
}
}

View File

@@ -582,7 +582,6 @@ class TestMyBizModel extends TestBizModel
$this->test_relations();
$this->test_linkedset();
$this->test_object_lifecycle();
return true;
}
}
@@ -929,7 +928,7 @@ class TestBulkChangeOnFarm extends TestBizModel
$aRes = $oBulk->Process($oMyChange);
print_r($aRes);
return true;
return;
$oRawData = array(
'Mammal',
@@ -978,7 +977,6 @@ class TestFullTextSearchOnFarm extends MyFarm
$oSearch->AddCondition_FullText('manof');
//$oResultSet = new DBObjectSet($oSearch);
$this->search_and_show_list($oSearch);
return true;
}
}
@@ -1103,7 +1101,6 @@ class TestItopEfficiency extends TestBizModel
$aData[] = $aValues;
}
echo MyHelpers::make_table_from_assoc_array($aData);
return true;
}
}
@@ -1169,8 +1166,6 @@ class TestItopWebServices extends TestWebServices
{
$this->DoExecSingleLoad($aLoadSpec);
}
return true;
}
}
@@ -1178,14 +1173,14 @@ class TestItopWebServices extends TestWebServices
$aWebServices = array(
array(
'verb' => 'GetVersion',
'expected result' => true,
'expected result' => '0.8',
'explain result' => 'n/a',
'args' => array(),
),
array(
'verb' => 'CreateIncidentTicket',
'expected result' => true,
'explain result' => 'ok, but link attribute unknown',
'explain result' => 'link attribute unknown + a CI not found',
'args' => array(
'admin', /* sLogin */
'admin', /* sPassword */
@@ -1195,7 +1190,7 @@ $aWebServices = array(
'very grave', /* sImpact */
new SOAPExternalKeySearch(array(new SOAPSearchCondition('id', 1))), /* aCallerDesc */
new SOAPExternalKeySearch(array(new SOAPSearchCondition('id', 2))), /* aCustomerDesc */
new SOAPExternalKeySearch(array(new SOAPSearchCondition('id', 1))), /* aWorkgroupDesc */
new SOAPExternalKeySearch(array(new SOAPSearchCondition('name', 'FLS Desktop'))), /* aWorkgroupDesc */
array(
new SOAPLinkCreationSpec(
'logInfra',
@@ -1207,14 +1202,38 @@ $aWebServices = array(
array(new SOAPSearchCondition('name', 'Router03')),
array(new SOAPAttributeValue('impact', 'who cares'))
),
new SOAPLinkCreationSpec(
'bizDevice',
array(new SOAPSearchCondition('name', 'thisone')),
array(new SOAPAttributeValue('impact', 'our lives'))
),
), /* aImpact */
'low' /* sSeverity */
),
),
array(
'verb' => 'CreateIncidentTicket',
'expected result' => true,
'explain result' => 'ok, but CI unknown',
'expected result' => false,
'explain result' => 'caller not specified',
'args' => array(
'admin', /* sLogin */
'admin', /* sPassword */
'Desktop', /* sType */
'PC burning', /* sDescription */
'The power supply suddenly started to warm up', /* sInitialSituation */
'The agent could not do his job', /* sImpact */
null, /* aCallerDesc */
new SOAPExternalKeySearch(array(new SOAPSearchCondition('id', 2))), /* aCustomerDesc */
new SOAPExternalKeySearch(array(new SOAPSearchCondition('name', 'FLS Desktop'))), /* aWorkgroupDesc */
array(
), /* aImpact */
'low' /* sSeverity */
),
),
array(
'verb' => 'CreateIncidentTicket',
'expected result' => false,
'explain result' => 'wrong condition on CI to attach',
'args' => array(
'admin', /* sLogin */
'admin', /* sPassword */
@@ -1224,11 +1243,11 @@ $aWebServices = array(
'The agent could not do his job', /* sImpact */
new SOAPExternalKeySearch(array(new SOAPSearchCondition('id', 1))), /* aCallerDesc */
new SOAPExternalKeySearch(array(new SOAPSearchCondition('id', 2))), /* aCustomerDesc */
new SOAPExternalKeySearch(array(new SOAPSearchCondition('id', 1))), /* aWorkgroupDesc */
new SOAPExternalKeySearch(array(new SOAPSearchCondition('name', 'FLS Desktop'))), /* aWorkgroupDesc */
array(
new SOAPLinkCreationSpec(
'logInfra',
array(new SOAPSearchCondition('id', 99999)),
array(new SOAPSearchCondition('dummyfiltercode', 2)),
array(new SOAPAttributeValue('impact', 'very critical'))
),
), /* aImpact */
@@ -1237,8 +1256,8 @@ $aWebServices = array(
),
array(
'verb' => 'CreateIncidentTicket',
'expected result' => false,
'explain result' => 'ok, no CI to attach',
'expected result' => true,
'explain result' => 'no CI to attach (empty array)',
'args' => array(
'admin', /* sLogin */
'admin', /* sPassword */
@@ -1248,12 +1267,30 @@ $aWebServices = array(
'Could not talk to my wife', /* sImpact */
new SOAPExternalKeySearch(array(new SOAPSearchCondition('id', 1))), /* aCallerDesc */
new SOAPExternalKeySearch(array(new SOAPSearchCondition('id', 2))), /* aCustomerDesc */
new SOAPExternalKeySearch(array(new SOAPSearchCondition('id', 1))), /* aWorkgroupDesc */
new SOAPExternalKeySearch(array(new SOAPSearchCondition('name', 'FLS Desktop'))), /* aWorkgroupDesc */
array(
), /* aImpact */
'low' /* sSeverity */
),
),
array(
'verb' => 'CreateIncidentTicket',
'expected result' => true,
'explain result' => 'no CI to attach (null)',
'args' => array(
'admin', /* sLogin */
'admin', /* sPassword */
'Network', /* sType */
'Houston not reachable', /* sDescription */
'Tried to join the shuttle', /* sInitialSituation */
'Could not talk to my wife', /* sImpact */
new SOAPExternalKeySearch(array(new SOAPSearchCondition('id', 1))), /* aCallerDesc */
new SOAPExternalKeySearch(array(new SOAPSearchCondition('id', 2))), /* aCustomerDesc */
new SOAPExternalKeySearch(array(new SOAPSearchCondition('name', 'FLS Desktop'))), /* aWorkgroupDesc */
null, /* aImpact */
'low' /* sSeverity */
),
),
array(
'verb' => 'CreateIncidentTicket',
'expected result' => false,
@@ -1267,12 +1304,31 @@ $aWebServices = array(
'Could not talk to my wife', /* sImpact */
new SOAPExternalKeySearch(array(new SOAPSearchCondition('id', 1000))), /* aCallerDesc */
new SOAPExternalKeySearch(array(new SOAPSearchCondition('id', 2))), /* aCustomerDesc */
new SOAPExternalKeySearch(array(new SOAPSearchCondition('id', 1))), /* aWorkgroupDesc */
new SOAPExternalKeySearch(array(new SOAPSearchCondition('name', 'FLS Desktop'))), /* aWorkgroupDesc */
array(
), /* aImpact */
'low' /* sSeverity */
),
),
array(
'verb' => 'CreateIncidentTicket',
'expected result' => false,
'explain result' => 'wrong values for type and severity',
'args' => array(
'admin', /* sLogin */
'admin', /* sPassword */
'my type', /* sType */
'Houston not reachable', /* sDescription */
'Tried to join the shuttle', /* sInitialSituation */
'Could not talk to my wife', /* sImpact */
new SOAPExternalKeySearch(array(new SOAPSearchCondition('id', 1))), /* aCallerDesc */
new SOAPExternalKeySearch(array(new SOAPSearchCondition('id', 2))), /* aCustomerDesc */
new SOAPExternalKeySearch(array(new SOAPSearchCondition('name', 'FLS Desktop'))), /* aWorkgroupDesc */
array(
), /* aImpact */
'my severity' /* sSeverity */
),
),
array(
'verb' => 'CreateIncidentTicket',
'expected result' => false,
@@ -1286,7 +1342,7 @@ $aWebServices = array(
'Could not talk to my wife', /* sImpact */
new SOAPExternalKeySearch(array(new SOAPSearchCondition('id', 1))), /* aCallerDesc */
new SOAPExternalKeySearch(array(new SOAPSearchCondition('id', 2))), /* aCustomerDesc */
new SOAPExternalKeySearch(array(new SOAPSearchCondition('id', 1))), /* aWorkgroupDesc */
new SOAPExternalKeySearch(array(new SOAPSearchCondition('name', 'FLS Desktop'))), /* aWorkgroupDesc */
array(
), /* aImpact */
'low' /* sSeverity */
@@ -1305,7 +1361,7 @@ $aWebServices = array(
'Could not talk to my wife', /* sImpact */
new SOAPExternalKeySearch(array(new SOAPSearchCondition('id', 1))), /* aCallerDesc */
new SOAPExternalKeySearch(array(new SOAPSearchCondition('id', 2))), /* aCustomerDesc */
new SOAPExternalKeySearch(array(new SOAPSearchCondition('id', 1))), /* aWorkgroupDesc */
new SOAPExternalKeySearch(array(new SOAPSearchCondition('name', 'FLS Desktop'))), /* aWorkgroupDesc */
array(
), /* aImpact */
'low' /* sSeverity */
@@ -1321,6 +1377,8 @@ class TestSoap extends TestSoapWebService
protected function DoExecute()
{
echo "<p>Note: You may also want to try the sample SOAP client <a href=\"../webservices/itopsoap.examples.php\">itopsoap.examples.php</a></p>\n";
global $aSOAPMapping;
// this file is generated dynamically with location = here
@@ -1331,7 +1389,6 @@ class TestSoap extends TestSoapWebService
(
$sWsdlUri,
array(
//'uri' => 'http://soap-itop/',
'classmap' => $aSOAPMapping,
'trace' => 1,
)
@@ -1348,6 +1405,7 @@ class TestSoap extends TestSoapWebService
foreach ($aWebServices as $iPos => $aWebService)
{
echo "<h4>SOAP call #$iPos ".$aWebService['explain result']."</h4>\n";
try
{
$oRes = call_user_func_array(array($this->m_SoapClient, $aWebService['verb']), $aWebService['args']);
@@ -1359,7 +1417,7 @@ class TestSoap extends TestSoapWebService
print "Response: \n".htmlspecialchars($this->m_SoapClient->__getLastResponse())."\n";
print "</pre>";
print "Response in HTML: <p>".$this->m_SoapClient->__getLastResponse()."</p>";
return false;
throw $e;
}
echo "<pre>\n";
@@ -1370,9 +1428,20 @@ class TestSoap extends TestSoapWebService
print "Request: \n".htmlspecialchars($this->m_SoapClient->__getLastRequest()) ."\n";
print "Response: \n".htmlspecialchars($this->m_SoapClient->__getLastResponse())."\n";
print "</pre>";
}
return true;
if ($oRes instanceof SOAPResult)
{
$res = $oRes->status;
}
else
{
$res = $oRes;
}
if ($res != $aWebService['expected result'])
{
throw new UnitTestException("Expecting result '{$aWebService['expected result']}', but got '$res'");
}
}
}
}

View File

@@ -1,6 +1,6 @@
<?xml version='1.0' encoding='UTF-8'?>
<!-- WSDL file originally generated by Zend Studio, then reworked manually -->
<!-- WSDL file generated manually -->
<definitions name="ITop" targetNamespace="urn:ITop" xmlns:typens="urn:ITop" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns="http://schemas.xmlsoap.org/wsdl/">
<types>
@@ -8,9 +8,13 @@
<!-- Added the following import tag to pass the Eclipse validation -->
<xsd:import namespace="http://schemas.xmlsoap.org/soap/encoding/" />
<xsd:complexType name="SearchCondition">
<!-- <wsdl:documentation>
A criteria to restrict a search (strict search is performed)
Example: name = 'myserver.combodo.fr'
</wsdl:documentation> -->
<xsd:all>
<xsd:element name="attcode" type="xsd:string"/>
<xsd:element name="value" type="xsd:anyType"/>
<xsd:element name="value" type="xsd:string"/> <!-- should be anyType but this one is not well supported by Eclipse -->
</xsd:all>
</xsd:complexType>
<xsd:complexType name="ArrayOfSearchCondition">
@@ -21,14 +25,23 @@
</xsd:complexContent>
</xsd:complexType>
<xsd:complexType name="ExternalKeySearch">
<!-- <wsdl:documentation>
Specifies [how to find] a value for an external key.
the class of object to search for will depend on the usage that is being made, therefore the search conditions that may be used will vary depending on the parameter that is concerned.
If one criteria is not relevant, then the match will not be attempted and warning will be logged (or an error if the target external key is mandatory)
Example: match on customer = 'Demo' and type = 'Router'
</wsdl:documentation> -->
<xsd:all>
<xsd:element name="conditions" type="typens:ArrayOfSearchCondition"/>
</xsd:all>
</xsd:complexType>
<xsd:complexType name="AttributeValue">
<!-- <wsdl:documentation>
Specifies a value to set
</wsdl:documentation> -->
<xsd:all>
<xsd:element name="attcode" type="xsd:string"/>
<xsd:element name="value" type="xsd:anyType"/>
<xsd:element name="value" type="xsd:string"/> <!-- should be anyType but this one is not well supported by Eclipse -->
</xsd:all>
</xsd:complexType>
<xsd:complexType name="ArrayOfAttributeValue">
@@ -39,6 +52,9 @@
</xsd:complexContent>
</xsd:complexType>
<xsd:complexType name="LinkCreationSpec">
<!-- <wsdl:documentation>
Specifies [how to match] one item to attach and what values should be set on the newly created link.
</wsdl:documentation> -->
<xsd:all>
<xsd:element name="class" type="xsd:string"/>
<xsd:element name="conditions" type="typens:ArrayOfSearchCondition"/>
@@ -53,6 +69,9 @@
</xsd:complexContent>
</xsd:complexType>
<xsd:complexType name="LogMessage">
<!-- <wsdl:documentation>
An event that happened during the execution of the web service
</wsdl:documentation> -->
<xsd:all>
<xsd:element name="text" type="xsd:string"/>
</xsd:all>
@@ -65,6 +84,9 @@
</xsd:complexContent>
</xsd:complexType>
<xsd:complexType name="ResultLog">
<!-- <wsdl:documentation>
A Log of events of the same category
</wsdl:documentation> -->
<xsd:all>
<xsd:element name="messages" type="typens:ArrayOfLogMessage"/>
</xsd:all>
@@ -72,7 +94,7 @@
<xsd:complexType name="ResultData">
<xsd:all>
<xsd:element name="key" type="xsd:string"/>
<xsd:element name="value" type="xsd:anyType"/>
<xsd:element name="value" type="xsd:string"/> <!-- should be anyType but this one is not well supported by Eclipse -->
</xsd:all>
</xsd:complexType>
<xsd:complexType name="ArrayOfResultData">
@@ -83,6 +105,10 @@
</xsd:complexContent>
</xsd:complexType>
<xsd:complexType name="ResultMessage">
<!-- <wsdl:documentation>
Output expected, depending on the operation invoked.
Example: CreateIncidentTicket will return 'created' => basic information on the created ticket
</wsdl:documentation> -->
<xsd:all>
<xsd:element name="label" type="xsd:string"/>
<xsd:element name="values" type="typens:ArrayOfResultData"/>
@@ -96,6 +122,12 @@
</xsd:complexContent>
</xsd:complexType>
<xsd:complexType name="Result">
<!-- <wsdl:documentation>
Standard result structure returned by all of the operations, excepted GetVersion (returning a string)
result holds returned data if the status is set to true
errors, warnings and infos will help in understanding what happened (unknown identifiers, object matching issues/results)
This resulting structure is being tracked into the application log as well.
</wsdl:documentation> -->
<xsd:all>
<xsd:element name="status" type="xsd:boolean"/>
<xsd:element name="result" type="typens:ArrayOfResultMessage"/>
@@ -129,17 +161,17 @@
</message>
<portType name="WebServicePortType">
<operation name="GetVersion">
<documentation>
<wsdl:documentation>
Get the current version of Itop
As this service is very simple, it is a test to get trained for more complex operations
</documentation>
</wsdl:documentation> -->
<input message="typens:GetVersion"/>
<output message="typens:GetVersionResponse"/>
</operation>
<operation name="CreateIncidentTicket">
<documentation>
<wsdl:documentation>
Create a ticket, return information about reconciliation on external keys and the created ticket
</documentation>
</wsdl:documentation> -->
<input message="typens:CreateIncidentTicket"/>
<output message="typens:CreateIncidentTicketResponse"/>
</operation>
@@ -166,6 +198,9 @@
</operation>
</binding>
<service name="ITopService">
<wsdl:documentation>
ITop is the central solution for managing your IT infrastructure
</wsdl:documentation>
<port name="WebServicePort" binding="typens:WebServiceBinding">
<soap:address location="___SOAP_SERVER_URI___"/>
</port>

View File

@@ -0,0 +1,69 @@
<?php
require_once('itopsoaptypes.class.inc.php');
$sItopRoot = 'http'.(empty($_SERVER['HTTPS']) ? '' : 's').'://'.$_SERVER['SERVER_NAME'].':'.$_SERVER['SERVER_PORT'].dirname($_SERVER['SCRIPT_NAME']).'/..';
$sWsdlUri = $sItopRoot.'/webservices/itop.wsdl.php';
ini_set("soap.wsdl_cache_enabled","0");
$oSoapClient = new SoapClient(
$sWsdlUri,
array(
'trace' => 1,
'classmap' => $aSOAPMapping, // defined in itopsoaptypes.class.inc.php
)
);
try
{
// The most simple service, returning a string
//
$sServerVersion = $oSoapClient->GetVersion();
echo "<p>GetVersion() returned <em>$sServerVersion</em></p>";
// More complex ones, returning a SOAPResult structure
// (run the page to know more about the returned data)
//
$oRes = $oSoapClient->CreateIncidentTicket
(
'admin', /* login */
'admin', /* password */
'Server', /* type */
'Email server down', /* description */
'HW found shutdown', /* initial situation */
'Email not working', /* impact */
null, /* caller */
new SOAPExternalKeySearch(array(new SOAPSearchCondition('name', 'Demo'))), /* customer */
new SOAPExternalKeySearch(array(new SOAPSearchCondition('id', 1))), /* workgroup */
array(
new SOAPLinkCreationSpec(
'bizDevice',
array(new SOAPSearchCondition('name', 'Router03')),
array(new SOAPAttributeValue('impact', 'root cause'))
),
new SOAPLinkCreationSpec(
'bizServer',
array(new SOAPSearchCondition('name', 'Server01')),
array(new SOAPAttributeValue('impact', ''))
),
), /* impact */
'high' /* severity */
);
echo "<p>CreateIncidentTicket() returned:\n";
echo "<pre>\n";
print_r($oRes);
echo "</pre>\n";
echo "</p>\n";
}
catch(SoapFault $e)
{
echo "<h1>SoapFault Exception: {$e->getMessage()}</h1>\n";
echo "<h2>Request</h2>\n";
echo "<pre>\n";
echo htmlspecialchars($oSoapClient->__getLastRequest())."\n";
echo "</pre>";
echo "<h2>Response</h2>";
echo $oSoapClient->__getLastResponse()."\n";
}
?>

View File

@@ -223,6 +223,14 @@ class WebServices
protected function LogUsage($sVerb, $oRes)
{
$oLog = new EventWebService();
if ($oRes->IsOk())
{
$oLog->Set('message', $sVerb.' was successfully invoked');
}
else
{
$oLog->Set('message', $sVerb.' returned errors');
}
$oLog->Set('userinfo', UserRights::GetUser());
$oLog->Set('verb', $sVerb);
$oLog->Set('result', $oRes->IsOk());
@@ -233,6 +241,29 @@ class WebServices
$oLog->DBInsertNoReload();
}
/**
* Helper to set a scalar attribute
*
* @param string sAttCode
* @param scalar value
* @param DBObject oTargetObj
* @param WebServiceResult oRes
*
*/
protected function MyObjectSetScalar($sAttCode, $sParamName, $value, &$oTargetObj, &$oRes)
{
if ($oTargetObj->CheckValue($sAttCode, $value))
{
$oTargetObj->Set($sAttCode, $value);
}
else
{
$aAllowedValues = MetaModel::GetAllowedValues_att(get_class($oTargetObj), $sAttCode);
$sValues = implode(', ', $aAllowedValues);
$oRes->LogError("Parameter $sParamName: found '$value' while expecting a value in {".$sValues."}");
}
}
/**
* Helper to set an external key
*
@@ -242,14 +273,28 @@ class WebServices
* @param WebServiceResult oRes
*
*/
protected function SetExternalKey($sAttCode, $aExtKeyDesc, &$oTargetObj, &$oRes)
protected function MyObjectSetExternalKey($sAttCode, $sParamName, $aExtKeyDesc, &$oTargetObj, &$oRes)
{
$oExtKey = MetaModel::GetAttributeDef(get_class($oTargetObj), $sAttCode);
$bIsMandatory = !$oExtKey->IsNullAllowed();
if (is_null($aExtKeyDesc))
{
if ($bIsMandatory)
{
$oRes->LogError("Parameter $sParamName: found null for a mandatory key");
}
else
{
// skip silently
return;
}
}
if (count($aExtKeyDesc) == 0)
{
$oRes->LogIssue("Ext key $sAttCode: no data was given to give a value to the key", $bIsMandatory);
$oRes->LogIssue("Parameter $sParamName: no search condition has been specified", $bIsMandatory);
return;
}
@@ -259,7 +304,8 @@ class WebServices
{
if (!MetaModel::IsValidFilterCode($sKeyClass, $sForeignAttCode))
{
$sMsg = "Ext key $sAttCode: '$sForeignAttCode' is not a valid filter code for class '$sKeyClass'";
$aCodes = array_keys(MetaModel::GetClassFilterDefs($sKeyClass));
$sMsg = "Parameter $sParamName: '$sForeignAttCode' is not a valid filter code for class '$sKeyClass', expecting a value in {".implode(', ', $aCodes)."}";
$oRes->LogIssue($sMsg, $bIsMandatory);
}
// The foreign attribute is one of our reconciliation key
@@ -269,7 +315,7 @@ class WebServices
switch($oExtObjects->Count())
{
case 0:
$sMsg = "External key $sAttCode could not be found (searched: '".$oReconFilter->ToOQL()."')";
$sMsg = "Parameter $sParamName: no match (searched: '".$oReconFilter->ToOQL()."')";
$oRes->LogIssue($sMsg, $bIsMandatory);
break;
case 1:
@@ -280,11 +326,11 @@ class WebServices
// Report it (no need to report if the object already had this value
if (array_key_exists($sAttCode, $oTargetObj->ListChanges()))
{
$oRes->LogInfo("$sAttCode has been set to ".$oForeignObj->GetKey());
$oRes->LogInfo("Parameter $sParamName: found match ".get_class($oForeignObj)."::".$oForeignObj->GetKey()." '".$oForeignObj->GetName()."'");
}
break;
default:
$sMsg = "Found ".$oExtObjects->Count()." matches for external key $sAttCode (searched: '".$oReconFilter->ToOQL()."')";
$sMsg = "Parameter $sParamName: Found ".$oExtObjects->Count()." matches (searched: '".$oReconFilter->ToOQL()."')";
$oRes->LogIssue($sMsg, $bIsMandatory);
}
}
@@ -300,7 +346,7 @@ class WebServices
*
* @return array List of objects that could not be found
*/
protected function AddLinkedObjects($sLinkAttCode, $sLinkedClass, $aLinkList, &$oTargetObj, &$oRes)
protected function AddLinkedObjects($sLinkAttCode, $sParamName, $sLinkedClass, $aLinkList, &$oTargetObj, &$oRes)
{
$oLinkAtt = MetaModel::GetAttributeDef(get_class($oTargetObj), $sLinkAttCode);
$sLinkClass = $oLinkAtt->GetLinkedClass();
@@ -308,22 +354,28 @@ class WebServices
$aItemsFound = array();
$aItemsNotFound = array();
if (is_null($aLinkList))
{
return $aItemsNotFound;
}
foreach ($aLinkList as $aItemData)
{
if (!array_key_exists('class', $aItemData))
{
$oRes->LogWarning("Linked object descriptor: missing 'class' specification");
$oRes->LogWarning("Parameter $sParamName: missing 'class' specification");
continue; // skip
}
$sTargetClass = $aItemData['class'];
if (!MetaModel::IsValidClass($sTargetClass))
{
$oRes->LogError("Invalid class $sTargetClass for impacted item");
$oRes->LogError("Parameter $sParamName: invalid class '$sTargetClass'");
continue; // skip
}
if (!MetaModel::IsParentClass($sLinkedClass, $sTargetClass))
{
$oRes->LogError("$sTargetClass is not a child class of $sLinkedClass");
$oRes->LogError("Parameter $sParamName: '$sTargetClass' is not a child class of '$sLinkedClass'");
continue; // skip
}
$oReconFilter = new CMDBSearchFilter($sTargetClass);
@@ -332,8 +384,9 @@ class WebServices
{
if (!MetaModel::IsValidFilterCode($sTargetClass, $sAttCode))
{
$oRes->LogError("Invalid filter code $sAttCode for class $sTargetClass");
continue; // skip
$aCodes = array_keys(MetaModel::GetClassFilterDefs($sTargetClass));
$oRes->LogError("Parameter $sParamName: '$sAttCode' is not a valid filter code for class '$sTargetClass', expecting a value in {".implode(', ', $aCodes)."}");
continue 2; // skip the entire item
}
$aCIStringDesc[] = "$sAttCode: $value";
@@ -355,7 +408,7 @@ class WebServices
switch($oExtObjects->Count())
{
case 0:
$oRes->LogWarning("Object to link $sLinkedClass / $sItemDesc could not be found (searched: '".$oReconFilter->ToOQL()."')");
$oRes->LogWarning("Parameter $sParamName: object to link $sLinkedClass / $sItemDesc could not be found (searched: '".$oReconFilter->ToOQL()."')");
$aItemsNotFound[] = $sItemDesc;
break;
case 1:
@@ -366,7 +419,7 @@ class WebServices
);
break;
default:
$oRes->LogWarning("Found ".$oExtObjects->Count()." matches for external key $sAttCode (searched: '".$oReconFilter->ToOQL()."')");
$oRes->LogWarning("Parameter $sParamName: Found ".$oExtObjects->Count()." matches for item '$sItemDesc' (searched: '".$oReconFilter->ToOQL()."')");
$aItemsNotFound[] = $sItemDesc;
}
}
@@ -382,7 +435,7 @@ class WebServices
{
if(!MetaModel::IsValidAttCode($sLinkClass, $sKey))
{
$oRes->LogWarning("Attaching item '".$aItemData['desc']."', the attribute code '$sKey' is not valid ; check the class '$sLinkClass'");
$oRes->LogWarning("Parameter $sParamName: Attaching item '".$aItemData['desc']."', the attribute code '$sKey' is not valid ; check the class '$sLinkClass'");
}
else
{
@@ -398,9 +451,28 @@ class WebServices
return $aItemsNotFound;
}
protected function MyObjectInsert($oTargetObj, $sResultLabel, $oChange, &$oRes)
{
if ($oRes->IsOk())
{
if ($oTargetObj->CheckToInsert())
{
$iId = $oTargetObj->DBInsertTrackedNoReload($oChange);
$oRes->LogInfo("Created object ".get_class($$oTargetObj)."::$iId");
$oRes->AddResultObject($sResultLabel, $oTargetObj);
}
else
{
$oRes->LogError("The ticket could not be created due to forbidden values (or inconsistent values)");
}
}
}
static protected function SoapStructToExternalKeySearch(SoapExternalKeySearch $oExternalKeySearch)
{
if (is_null($oExternalKeySearch)) return null;
$aRes = array();
foreach($oExternalKeySearch->conditions as $oSearchCondition)
{
@@ -504,36 +576,26 @@ class WebServices
$iChangeId = $oMyChange->DBInsertNoReload();
$oNewTicket = MetaModel::NewObject('bizIncidentTicket');
$oNewTicket->Set('type', $sType);
$oNewTicket->Set('title', $sDescription);
$oNewTicket->Set('initial_situation', $sInitialSituation);
$oNewTicket->Set('severity', $sSeverity);
$this->MyObjectSetScalar('type', 'type', $sType, $oNewTicket, $oRes);
$this->MyObjectSetScalar('title', 'title', $sDescription, $oNewTicket, $oRes);
$this->MyObjectSetScalar('initial_situation', 'initialsituation', $sInitialSituation, $oNewTicket, $oRes);
$this->MyObjectSetScalar('severity', 'severity', $sSeverity, $oNewTicket, $oRes);
$this->SetExternalKey('org_id', $aCustomerDesc, $oNewTicket, $oRes);
$this->SetExternalKey('caller_id', $aCallerDesc, $oNewTicket, $oRes);
$this->SetExternalKey('workgroup_id', $aWorkgroupDesc, $oNewTicket, $oRes);
$this->MyObjectSetExternalKey('org_id', 'customer', $aCustomerDesc, $oNewTicket, $oRes);
$this->MyObjectSetExternalKey('caller_id', 'caller', $aCallerDesc, $oNewTicket, $oRes);
$this->MyObjectSetExternalKey('workgroup_id', 'workgroup', $aWorkgroupDesc, $oNewTicket, $oRes);
$aDevicesNotFound = $this->AddLinkedObjects('impacted_infra_manual', 'logInfra', $aImpactedCIs, $oNewTicket, $oRes);
$aDevicesNotFound = $this->AddLinkedObjects('impacted_infra_manual', 'impacted_cis', 'logInfra', $aImpactedCIs, $oNewTicket, $oRes);
if (count($aDevicesNotFound) > 0)
{
$oNewTicket->Set('impact', $sImpact.' - Related CIs: '.implode(', ', $aDevicesNotFound));
$this->MyObjectSetScalar('impact', 'n/a', $sImpact.' - Related CIs: '.implode(', ', $aDevicesNotFound), $oNewTicket, $oRes);
}
else
{
$oNewTicket->Set('impact', $sImpact);
}
if (!$oNewTicket->CheckToInsert())
{
$oRes->LogError("The ticket could not be created due to forbidden values (or inconsistent values)");
}
if ($oRes->IsOk())
{
$iId = $oNewTicket->DBInsertTrackedNoReload($oMyChange);
$oRes->LogInfo("Created ticket #$iId");
$oRes->AddResultObject('created', $oNewTicket);
$this->MyObjectSetScalar('impact', 'n/a', $sImpact, $oNewTicket, $oRes);
}
$this->MyObjectInsert($oNewTicket, 'created', $oMyChange, $oRes);
}
catch (CoreException $e)
{