|
@@ -61,448 +61,149 @@
|
|
|
if (!defined('__DIR__')) define('__DIR__', dirname(__FILE__));
|
|
|
require_once(__DIR__.'/../approot.inc.php');
|
|
|
require_once(APPROOT.'/application/application.inc.php');
|
|
|
-require_once(APPROOT.'/application/clipage.class.inc.php');
|
|
|
+require_once(APPROOT.'/application/ajaxwebpage.class.inc.php');
|
|
|
require_once(APPROOT.'/application/startup.inc.php');
|
|
|
|
|
|
+require_once(APPROOT.'core/restservices.class.inc.php');
|
|
|
|
|
|
|
|
|
-class RestServices
|
|
|
+/**
|
|
|
+ * Result structure that is specific to the hardcoded verb 'list_operations'
|
|
|
+ */
|
|
|
+class RestResultListOperations extends RestResult
|
|
|
{
|
|
|
- public function InitTrackingComment($oData)
|
|
|
- {
|
|
|
- $sComment = $this->GetMandatoryParam($oData, 'comment');
|
|
|
- CMDBObject::SetTrackInfo($sComment);
|
|
|
- }
|
|
|
+ public $version;
|
|
|
+ public $operations;
|
|
|
|
|
|
-
|
|
|
- public function GetMandatoryParam($oData, $sParamName)
|
|
|
+ public function AddOperation($sVerb, $sDescription, $sServiceProviderClass)
|
|
|
{
|
|
|
- if (isset($oData->$sParamName))
|
|
|
- {
|
|
|
- return $oData->$sParamName;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- throw new Exception("Missing parameter '$sParamName'");
|
|
|
- }
|
|
|
+ $this->operations[] = array(
|
|
|
+ 'verb' => $sVerb,
|
|
|
+ 'description' => $sDescription,
|
|
|
+ 'extension' => $sServiceProviderClass
|
|
|
+ );
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
+////////////////////////////////////////////////////////////////////////////////
|
|
|
+//
|
|
|
+// Main
|
|
|
+//
|
|
|
+$oP = new ajax_page('rest');
|
|
|
|
|
|
- public function GetOptionalParam($oData, $sParamName, $default)
|
|
|
+try
|
|
|
+{
|
|
|
+ utils::UseParamFile();
|
|
|
+
|
|
|
+ $sAuthUser = utils::ReadPostedParam('auth_user', null, 'raw_data');
|
|
|
+ $sAuthPwd = utils::ReadPostedParam('auth_pwd', null, 'raw_data');
|
|
|
+ if (UserRights::CheckCredentials($sAuthUser, $sAuthPwd))
|
|
|
{
|
|
|
- if (isset($oData->$sParamName))
|
|
|
- {
|
|
|
- return $oData->$sParamName;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- return $default;
|
|
|
- }
|
|
|
+ UserRights::Login($sAuthUser); // Login & set the user's language
|
|
|
}
|
|
|
-
|
|
|
-
|
|
|
- public function GetClass($oData, $sParamName)
|
|
|
+ else
|
|
|
{
|
|
|
- $sClass = $this->GetMandatoryParam($oData, $sParamName);
|
|
|
- if (!MetaModel::IsValidClass($sClass))
|
|
|
- {
|
|
|
- throw new Exception("$sParamName: '$sClass' is not a valid class'");
|
|
|
- }
|
|
|
- return $sClass;
|
|
|
+ throw new Exception("Invalid login '$sAuthUser'", RestResult::UNAUTHORIZED);
|
|
|
}
|
|
|
|
|
|
-
|
|
|
- public function GetFieldList($sClass, $oData, $sParamName)
|
|
|
+ $sVersion = utils::ReadParam('version', null, false, 'raw_data');
|
|
|
+ if ($sVersion == null)
|
|
|
{
|
|
|
- $sFields = $this->GetOptionalParam($oData, $sParamName, '*');
|
|
|
- $aShowFields = array();
|
|
|
- if ($sFields == '*')
|
|
|
- {
|
|
|
- foreach (MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef)
|
|
|
- {
|
|
|
- $aShowFields[] = $sAttCode;
|
|
|
- }
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- foreach(explode(',', $sFields) as $sAttCode)
|
|
|
- {
|
|
|
- $sAttCode = trim($sAttCode);
|
|
|
- if (($sAttCode != 'id') && (!MetaModel::IsValidAttCode($sClass, $sAttCode)))
|
|
|
- {
|
|
|
- throw new Exception("$sParamName: invalid attribute code '$sAttCode'");
|
|
|
- }
|
|
|
- $aShowFields[] = $sAttCode;
|
|
|
- }
|
|
|
- }
|
|
|
- return $aShowFields;
|
|
|
+ throw new Exception("Missing parameter 'version' (e.g. '1.0')", RestResult::MISSING_VERSION);
|
|
|
}
|
|
|
-
|
|
|
- protected function FindObjectFromCriteria($sClass, $oCriteria)
|
|
|
+
|
|
|
+ $sJsonString = utils::ReadPostedParam('json_data', null, 'raw_data');
|
|
|
+ if ($sJsonString == null)
|
|
|
{
|
|
|
- $aCriteriaReport = array();
|
|
|
- if (isset($oCriteria->finalclass))
|
|
|
- {
|
|
|
- $sClass = $oCriteria->finalclass;
|
|
|
- if (!MetaModel::IsValidClass($sClass))
|
|
|
- {
|
|
|
- throw new Exception("finalclass: Unknown class '$sClass'");
|
|
|
- }
|
|
|
- }
|
|
|
- $oSearch = new DBObjectSearch($sClass);
|
|
|
- foreach ($oCriteria as $sAttCode => $value)
|
|
|
- {
|
|
|
- $realValue = $this->MakeValue($sClass, $sAttCode, $value);
|
|
|
- $oSearch->AddCondition($sAttCode, $realValue);
|
|
|
- $aCriteriaReport[] = "$sAttCode: $value ($realValue)";
|
|
|
- }
|
|
|
- $oSet = new DBObjectSet($oSearch);
|
|
|
- $iCount = $oSet->Count();
|
|
|
- if ($iCount == 0)
|
|
|
- {
|
|
|
- throw new Exception("No item found for criteria: ".implode(', ', $aCriteriaReport));
|
|
|
- }
|
|
|
- elseif ($iCount > 1)
|
|
|
- {
|
|
|
- throw new Exception("Several items found ($iCount) for criteria: ".implode(', ', $aCriteriaReport));
|
|
|
- }
|
|
|
- $res = $oSet->Fetch();
|
|
|
- return $res;
|
|
|
+ throw new Exception("Missing parameter 'json_data", RestResult::MISSING_JSON);
|
|
|
}
|
|
|
-
|
|
|
-
|
|
|
- public function FindObjectFromKey($sClass, $key)
|
|
|
+ $aJsonData = json_decode($sJsonString);
|
|
|
+ if ($aJsonData == null)
|
|
|
{
|
|
|
- if (is_object($key))
|
|
|
- {
|
|
|
- $res = $this->FindObjectFromCriteria($sClass, $key);
|
|
|
- }
|
|
|
- elseif (is_numeric($key))
|
|
|
- {
|
|
|
- $res = MetaModel::GetObject($sClass, $key);
|
|
|
- }
|
|
|
- elseif (is_string($key))
|
|
|
- {
|
|
|
- // OQL
|
|
|
- $oSearch = DBObjectSearch::FromOQL($key);
|
|
|
- $oSet = new DBObjectSet($oSearch);
|
|
|
- $iCount = $oSet->Count();
|
|
|
- if ($iCount == 0)
|
|
|
- {
|
|
|
- throw new Exception("No item found for query: $key");
|
|
|
- }
|
|
|
- elseif ($iCount > 1)
|
|
|
- {
|
|
|
- throw new Exception("Several items found ($iCount) for query: $key");
|
|
|
- }
|
|
|
- $res = $oSet->Fetch();
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- throw new Exception("Wrong format for key");
|
|
|
- }
|
|
|
- return $res;
|
|
|
+ throw new Exception("Parameter json_data is not a valid JSON structure", RestResult::INVALID_JSON);
|
|
|
}
|
|
|
|
|
|
|
|
|
- public function GetObjectSetFromKey($sClass, $key)
|
|
|
+ $aProviders = array();
|
|
|
+ foreach(get_declared_classes() as $sPHPClass)
|
|
|
{
|
|
|
- if (is_object($key))
|
|
|
+ $oRefClass = new ReflectionClass($sPHPClass);
|
|
|
+ if ($oRefClass->implementsInterface('iRestServiceProvider'))
|
|
|
{
|
|
|
- if (isset($oCriteria->finalclass))
|
|
|
- {
|
|
|
- $sClass = $oCriteria->finalclass;
|
|
|
- if (!MetaModel::IsValidClass($sClass))
|
|
|
- {
|
|
|
- throw new Exception("finalclass: Unknown class '$sClass'");
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- $oSearch = new DBObjectSearch($sClass);
|
|
|
- foreach ($key as $sAttCode => $value)
|
|
|
- {
|
|
|
- $realValue = $this->MakeValue($sClass, $sAttCode, $value);
|
|
|
- $oSearch->AddCondition($sAttCode, $realValue);
|
|
|
- }
|
|
|
+ $aProviders[] = new $sPHPClass;
|
|
|
}
|
|
|
- elseif (is_numeric($key))
|
|
|
- {
|
|
|
- $oSearch = new DBObjectSearch($sClass);
|
|
|
- $oSearch->AddCondition('id', $key);
|
|
|
- }
|
|
|
- elseif (is_string($key))
|
|
|
- {
|
|
|
- // OQL
|
|
|
- $oSearch = DBObjectSearch::FromOQL($key);
|
|
|
- $oObjectSet = new DBObjectSet($oSearch);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- throw new Exception("Wrong format for key");
|
|
|
- }
|
|
|
- $oObjectSet = new DBObjectSet($oSearch);
|
|
|
- return $oObjectSet;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
- protected function MakeValue($sClass, $sAttCode, $value)
|
|
|
+ $aOpToRestService = array(); // verb => $oRestServiceProvider
|
|
|
+ foreach ($aProviders as $oRestSP)
|
|
|
{
|
|
|
- try
|
|
|
+ $aOperations = $oRestSP->ListOperations($sVersion);
|
|
|
+ foreach ($aOperations as $aOpData)
|
|
|
{
|
|
|
- if (!MetaModel::IsValidAttCode($sClass, $sAttCode))
|
|
|
- {
|
|
|
- throw new Exception("Unknown attribute");
|
|
|
- }
|
|
|
- $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
|
|
|
- if ($oAttDef instanceof AttributeExternalKey)
|
|
|
- {
|
|
|
- $oExtKeyObject = $this->FindObjectFromKey($oAttDef->GetTargetClass(), $value);
|
|
|
- $value = $oExtKeyObject->GetKey();
|
|
|
- }
|
|
|
- elseif ($oAttDef instanceof AttributeLinkedSet)
|
|
|
- {
|
|
|
- if (!is_array($value))
|
|
|
- {
|
|
|
- throw new Exception("A link set must be defined by an array of objects");
|
|
|
- }
|
|
|
- $sLnkClass = $oAttDef->GetLinkedClass();
|
|
|
- $aLinks = array();
|
|
|
- foreach($value as $oValues)
|
|
|
- {
|
|
|
- $oLnk = $this->MakeObjectFromFields($sLnkClass, $oValues);
|
|
|
- $aLinks[] = $oLnk;
|
|
|
- }
|
|
|
- $value = DBObjectSet::FromArray($sLnkClass, $aLinks);
|
|
|
- }
|
|
|
+ $aOpToRestService[$aOpData['verb']] = array
|
|
|
+ (
|
|
|
+ 'service_provider' => $oRestSP,
|
|
|
+ 'description' => $aOpData['description'],
|
|
|
+ );
|
|
|
}
|
|
|
- catch (Exception $e)
|
|
|
- {
|
|
|
- throw new Exception("$sAttCode: ".$e->getMessage());
|
|
|
- }
|
|
|
- return $value;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
- public function MakeObjectFromFields($sClass, $aFields)
|
|
|
+ if (count($aOpToRestService) == 0)
|
|
|
{
|
|
|
- $oObject = MetaModel::NewObject($sClass);
|
|
|
- foreach ($aFields as $sAttCode => $value)
|
|
|
- {
|
|
|
- $realValue = $this->MakeValue($sClass, $sAttCode, $value);
|
|
|
- $oObject->Set($sAttCode, $realValue);
|
|
|
- }
|
|
|
- return $oObject;
|
|
|
+ throw new Exception("There is no service available for version '$sVersion'", RestResult::UNSUPPORTED_VERSION);
|
|
|
}
|
|
|
|
|
|
|
|
|
- public function UpdateObjectFromFields($oObject, $aFields)
|
|
|
+ $sOperation = RestUtils::GetMandatoryParam($aJsonData, 'operation');
|
|
|
+ if ($sOperation == 'list_operations')
|
|
|
{
|
|
|
- $sClass = get_class($oObject);
|
|
|
- foreach ($aFields as $sAttCode => $value)
|
|
|
+ $oResult = new RestResultListOperations();
|
|
|
+ $oResult->message = "Operations: ".count($aOpToRestService);
|
|
|
+ $oResult->version = $sVersion;
|
|
|
+ foreach ($aOpToRestService as $sVerb => $aOpData)
|
|
|
{
|
|
|
- $realValue = $this->MakeValue($sClass, $sAttCode, $value);
|
|
|
- $oObject->Set($sAttCode, $realValue);
|
|
|
+ $oResult->AddOperation($sVerb, $aOpData['description'], get_class($aOpData['service_provider']));
|
|
|
}
|
|
|
- return $oObject;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-class FieldResult
|
|
|
-{
|
|
|
- protected $value;
|
|
|
-
|
|
|
- public function __construct()
|
|
|
- {
|
|
|
- }
|
|
|
-
|
|
|
- public function GetValue()
|
|
|
- {
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-class ObjectResult
|
|
|
-{
|
|
|
- public $code;
|
|
|
- public $message;
|
|
|
- public $fields;
|
|
|
-
|
|
|
- public function __construct()
|
|
|
- {
|
|
|
- $this->code = 0;
|
|
|
- $this->message = '';
|
|
|
- $this->fields = array();
|
|
|
}
|
|
|
-
|
|
|
- protected function MakeResultValue($oObject, $sAttCode)
|
|
|
+ else
|
|
|
{
|
|
|
- if ($sAttCode == 'id')
|
|
|
+ if (!array_key_exists($sOperation, $aOpToRestService))
|
|
|
{
|
|
|
- $value = $oObject->GetKey();
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- $sClass = get_class($oObject);
|
|
|
- $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
|
|
|
- if ($oAttDef instanceof AttributeLinkedSet)
|
|
|
- {
|
|
|
- $value = array();
|
|
|
-
|
|
|
- // Make the list of required attributes
|
|
|
- // - Skip attributes pointing to the current object (redundant data)
|
|
|
- // - Skip link sets refering to the current data (infinite recursion!)
|
|
|
- $aRelevantAttributes = array();
|
|
|
- $sLnkClass = $oAttDef->GetLinkedClass();
|
|
|
- foreach (MetaModel::ListAttributeDefs($sLnkClass) as $sLnkAttCode => $oLnkAttDef)
|
|
|
- {
|
|
|
- // Skip any attribute of the link that points to the current object
|
|
|
- //
|
|
|
- if ($sLnkAttCode == $oAttDef->GetExtKeyToMe()) continue;
|
|
|
- if (method_exists($oLnkAttDef, 'GetKeyAttCode'))
|
|
|
- {
|
|
|
- if ($oLnkAttDef->GetKeyAttCode() ==$oAttDef->GetExtKeyToMe()) continue;
|
|
|
- }
|
|
|
-
|
|
|
- $aRelevantAttributes[] = $sLnkAttCode;
|
|
|
- }
|
|
|
-
|
|
|
- // Iterate on the set and build an array of array of attcode=>value
|
|
|
- $oSet = $oObject->Get($sAttCode);
|
|
|
- while ($oLnk = $oSet->Fetch())
|
|
|
- {
|
|
|
- $aLnkValues = array();
|
|
|
- foreach ($aRelevantAttributes as $sLnkAttCode)
|
|
|
- {
|
|
|
- $aLnkValues[$sLnkAttCode] = $this->MakeResultValue($oLnk, $sLnkAttCode);
|
|
|
- }
|
|
|
- $value[] = $aLnkValues;
|
|
|
- }
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- $value = $oObject->GetEditValue($sAttCode);
|
|
|
- }
|
|
|
+ throw new Exception("Unknown verb '$sVersion'", RestResult::UNKNOWN_OPERATION);
|
|
|
}
|
|
|
- return $value;
|
|
|
- }
|
|
|
-
|
|
|
- public function AddField($oObject, $sAttCode)
|
|
|
- {
|
|
|
- $this->fields[$sAttCode] = $this->MakeResultValue($oObject, $sAttCode);
|
|
|
+ $oRS = $aOpToRestService[$sOperation]['service_provider'];
|
|
|
+
|
|
|
+ $oResult = $oRS->ExecOperation($sVersion, $sOperation, $aJsonData);
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
-class RestResult
|
|
|
+catch(Exception $e)
|
|
|
{
|
|
|
- public function __construct()
|
|
|
+ $oResult = new RestResult();
|
|
|
+ if ($e->GetCode() == 0)
|
|
|
{
|
|
|
+ $oResult->code = RestResult::INTERNAL_ERROR;
|
|
|
}
|
|
|
-
|
|
|
- public $code;
|
|
|
- public $message;
|
|
|
- public $objects;
|
|
|
-
|
|
|
- public function AddObject($iCode, $sMessage, $oObject = null, $aFields = null)
|
|
|
+ else
|
|
|
{
|
|
|
- $oObjRes = new ObjectResult();
|
|
|
- $oObjRes->code = $iCode;
|
|
|
- $oObjRes->message = $sMessage;
|
|
|
-
|
|
|
- if ($oObject)
|
|
|
- {
|
|
|
- foreach ($aFields as $sAttCode)
|
|
|
- {
|
|
|
- $oObjRes->AddField($oObject, $sAttCode);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- $this->objects[] = $oObjRes;
|
|
|
+ $oResult->code = $e->GetCode();
|
|
|
}
|
|
|
+ $oResult->message = "Error: ".$e->GetMessage();
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-
|
|
|
-////////////////////////////////////////////////////////////////////////////////
|
|
|
+// Output the results
|
|
|
//
|
|
|
-// Main
|
|
|
-//
|
|
|
-$oP = new CLIPage("iTop - REST");
|
|
|
-$oResult = new RestResult();
|
|
|
+$oP->add_header('Access-Control-Allow-Origin: *');
|
|
|
|
|
|
-try
|
|
|
+$sCallback = utils::ReadParam('callback', null);
|
|
|
+if ($sCallback == null)
|
|
|
{
|
|
|
- utils::UseParamFile();
|
|
|
-
|
|
|
- $sAuthUser = utils::ReadPostedParam('auth_user', null, 'raw_data');
|
|
|
- $sAuthPwd = utils::ReadPostedParam('auth_pwd', null, 'raw_data');
|
|
|
- if (UserRights::CheckCredentials($sAuthUser, $sAuthPwd))
|
|
|
- {
|
|
|
- UserRights::Login($sAuthUser); // Login & set the user's language
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- throw new Exception("Invalid login '$sAuthUser'");
|
|
|
- }
|
|
|
-
|
|
|
- $aJsonData = json_decode(utils::ReadPostedParam('json_data', null, 'raw_data'));
|
|
|
- if ($aJsonData == null)
|
|
|
- {
|
|
|
- throw new Exception('Parameter json_data is not a valid JSON structure');
|
|
|
- }
|
|
|
-
|
|
|
- $oRS = new RestServices();
|
|
|
-
|
|
|
- $sOperation = $oRS->GetMandatoryParam($aJsonData, 'operation');
|
|
|
- switch ($sOperation)
|
|
|
- {
|
|
|
- case 'object_create':
|
|
|
- $oRS->InitTrackingComment($aJsonData);
|
|
|
- $sClass = $oRS->GetClass($aJsonData, 'class');
|
|
|
- $aFields = $oRS->GetMandatoryParam($aJsonData, 'fields');
|
|
|
- $aShowFields = $oRS->GetFieldList($sClass, $aJsonData, 'results');
|
|
|
-
|
|
|
- $oObject = $oRS->MakeObjectFromFields($sClass, $aFields);
|
|
|
- $oObject->DBInsert();
|
|
|
-
|
|
|
- $oResult->AddObject(0, 'created', $oObject, $aShowFields);
|
|
|
- break;
|
|
|
-
|
|
|
- case 'object_update':
|
|
|
- $oRS->InitTrackingComment($aJsonData);
|
|
|
- $sClass = $oRS->GetClass($aJsonData, 'class');
|
|
|
- $key = $oRS->GetMandatoryParam($aJsonData, 'key');
|
|
|
- $aFields = $oRS->GetMandatoryParam($aJsonData, 'fields');
|
|
|
- $aShowFields = $oRS->GetFieldList($sClass, $aJsonData, 'results');
|
|
|
-
|
|
|
- $oObject = $oRS->FindObjectFromKey($sClass, $key);
|
|
|
- $oRS->UpdateObjectFromFields($oObject, $aFields);
|
|
|
- $oObject->DBUpdate();
|
|
|
-
|
|
|
- $oResult->AddObject(0, 'updated', $oObject, $aShowFields);
|
|
|
- break;
|
|
|
-
|
|
|
- case 'object_get':
|
|
|
- $sClass = $oRS->GetClass($aJsonData, 'class');
|
|
|
- $key = $oRS->GetMandatoryParam($aJsonData, 'key');
|
|
|
- $aShowFields = $oRS->GetFieldList($sClass, $aJsonData, 'results');
|
|
|
-
|
|
|
- $oObjectSet = $oRS->GetObjectSetFromKey($sClass, $key);
|
|
|
- while ($oObject = $oObjectSet->Fetch())
|
|
|
- {
|
|
|
- $oResult->AddObject(0, '', $oObject, $aShowFields);
|
|
|
- }
|
|
|
- $oResult->message = "Found: ".$oObjectSet->Count();
|
|
|
- break;
|
|
|
-
|
|
|
- default:
|
|
|
- throw new Exception("Uknown operation '$sOperation'");
|
|
|
- }
|
|
|
+ $oP->SetContentType('application/json');
|
|
|
+ $oP->add(json_encode($oResult));
|
|
|
}
|
|
|
-catch(Exception $e)
|
|
|
+else
|
|
|
{
|
|
|
- $oResult->code = 1234;
|
|
|
- $oResult->message = "Error: ".$e->GetMessage();
|
|
|
+ $oP->SetContentType('application/javascript');
|
|
|
+ $oP->add($sCallback.'('.json_encode($oResult).')');
|
|
|
}
|
|
|
-
|
|
|
-$oP->add(json_encode($oResult));
|
|
|
$oP->Output();
|
|
|
?>
|