From 3d79e3fe8f1c2a9610c65aa590fc920916844432 Mon Sep 17 00:00:00 2001 From: Romain Quetiez Date: Tue, 2 Apr 2013 13:31:52 +0000 Subject: [PATCH] #472 REST API: finalized the implementation of core/get_related + added the support for AttributeBlob (to manage documents and attachments) SVN:trunk[2669] --- application/applicationextension.inc.php | 4 ++ core/attributedef.class.inc.php | 63 ++++++++++++++++++++++++ core/restservices.class.inc.php | 53 ++++++++++++-------- webservices/itoprest.examples.php | 7 +++ 4 files changed, 106 insertions(+), 21 deletions(-) diff --git a/application/applicationextension.inc.php b/application/applicationextension.inc.php index 0db84df46..1a98a8dde 100644 --- a/application/applicationextension.inc.php +++ b/application/applicationextension.inc.php @@ -909,6 +909,10 @@ class RestUtils } $value = DBObjectSet::FromArray($sLnkClass, $aLinks); } + else + { + $value = $oAttDef->FromJSONToValue($value); + } } catch (Exception $e) { diff --git a/core/attributedef.class.inc.php b/core/attributedef.class.inc.php index d30d80e4d..92863ba01 100644 --- a/core/attributedef.class.inc.php +++ b/core/attributedef.class.inc.php @@ -426,6 +426,26 @@ abstract class AttributeDefinition return (string)$sValue; } + /** + * Helper to get a value that will be JSON encoded + * The operation is the opposite to FromJSONToValue + */ + public function GetForJSON($value) + { + // In most of the cases, that will be the expected behavior... + return $this->GetEditValue($value); + } + + /** + * Helper to form a value, given JSON decoded data + * The operation is the opposite to GetForJSON + */ + public function FromJSONToValue($json) + { + // Passthrough in most of the cases + return $json; + } + /** * Override to display the value in the GUI */ @@ -3322,6 +3342,11 @@ class AttributeBlob extends AttributeDefinition public function GetDefaultValue() {return "";} public function IsNullAllowed() {return $this->GetOptional("is_null_allowed", false);} + public function GetEditValue($sValue, $oHostObj = null) + { + return ''; + } + // Facilitate things: allow the user to Set the value from a string public function MakeRealValue($proposedValue, $oHostObj) @@ -3450,6 +3475,44 @@ class AttributeBlob extends AttributeDefinition { return ''; // Not exportable in XML, or as CDATA + some subtags ?? } + + /** + * Helper to get a value that will be JSON encoded + * The operation is the opposite to FromJSONToValue + */ + public function GetForJSON($value) + { + if ($value instanceOf ormDocument) + { + $aValues = array(); + $aValues['data'] = base64_encode($value->GetData()); + $aValues['mimetype'] = $value->GetMimeType(); + $aValues['filename'] = $value->GetFileName(); + } + else + { + $aValues = null; + } + return $aValues; + } + + /** + * Helper to form a value, given JSON decoded data + * The operation is the opposite to GetForJSON + */ + public function FromJSONToValue($json) + { + if (isset($json->data)) + { + $data = base64_decode($json->data); + $value = new ormDocument($data, $json->mimetype, $json->filename); + } + else + { + $value = null; + } + return $value; + } } /** diff --git a/core/restservices.class.inc.php b/core/restservices.class.inc.php index 6193c8464..025ae847e 100644 --- a/core/restservices.class.inc.php +++ b/core/restservices.class.inc.php @@ -99,14 +99,9 @@ class ObjectResult $value[] = $aLnkValues; } } - elseif ($oAttDef->IsExternalKey()) - { - $value = $oObject->Get($sAttCode); - } else { - // Still to be refined... - $value = $oObject->GetEditValue($sAttCode); + $value = $oAttDef->GetForJSON($oObject->Get($sAttCode)); } } return $value; @@ -147,22 +142,20 @@ class RestResultWithObjects extends RestResult * @param array $aFields An array of attribute codes. List of the attributes to be reported. * @return void */ - public function AddObject($iCode, $sMessage, $oObject = null, $aFields = null) + public function AddObject($iCode, $sMessage, $oObject, $aFields) { $oObjRes = new ObjectResult(); $oObjRes->code = $iCode; $oObjRes->message = $sMessage; - if ($oObject) + $oObjRes->class = get_class($oObject); + foreach ($aFields as $sAttCode) { - $oObjRes->class = get_class($oObject); - foreach ($aFields as $sAttCode) - { - $oObjRes->AddField($oObject, $sAttCode); - } + $oObjRes->AddField($oObject, $sAttCode); } - $this->objects[] = $oObjRes; + $sObjKey = get_class($oObject).'::'.$oObject->GetKey(); + $this->objects[$sObjKey] = $oObjRes; } } @@ -182,7 +175,7 @@ class RestResultWithRelations extends RestResultWithObjects { $this->relations[$sSrcKey] = array(); } - $this->relations[$sSrcKey][] = $sDestKey; + $this->relations[$sSrcKey][] = array('key' => $sDestKey); } } @@ -389,14 +382,16 @@ class CoreServices implements iRestServiceProvider $sClass = RestUtils::GetClass($aParams, 'class'); $key = RestUtils::GetMandatoryParam($aParams, 'key'); $sRelation = RestUtils::GetMandatoryParam($aParams, 'relation'); - $iMaxRecursionDepth = RestUtils::GetOptionalParam($aParams, 'depth', 20 /* = MAX_RECUSTION_DEPTH */); - $aShowFields = RestUtils::GetFieldList($sClass, $aParams, 'output_fields'); + $iMaxRecursionDepth = RestUtils::GetOptionalParam($aParams, 'depth', 20 /* = MAX_RECURSION_DEPTH */); + $aShowFields = array('id', 'friendlyname'); $oObjectSet = RestUtils::GetObjectSetFromKey($sClass, $key); + $aIndexByClass = array(); while ($oObject = $oObjectSet->Fetch()) { $aRelated = array(); $aGraph = array(); + $aIndexByClass[get_class($oObject)][$oObject->GetKey()] = null; $oResult->AddObject(0, '', $oObject, $aShowFields); $this->GetRelatedObjects($oObject, $sRelation, $iMaxRecursionDepth, $aRelated, $aGraph); @@ -404,15 +399,31 @@ class CoreServices implements iRestServiceProvider { foreach($aObjects as $oRelatedObj) { + $aIndexByClass[get_class($oRelatedObj)][$oRelatedObj->GetKey()] = null; $oResult->AddObject(0, '', $oRelatedObj, $aShowFields); } } - foreach($aGraph as $sSrcKey => $sDestKey) + foreach($aGraph as $sSrcKey => $aDestinations) { - $oResult->AddRelation($sSrcKey, $sDestKey); + foreach ($aDestinations as $sDestKey) + { + $oResult->AddRelation($sSrcKey, $sDestKey); + } } - } - $oResult->message = "Found: ".$oObjectSet->Count(); + } + if (count($aIndexByClass) > 0) + { + $aStats = array(); + foreach ($aIndexByClass as $sClass => $aIds) + { + $aStats[] = $sClass.'= '.count($aIds); + } + $oResult->message = "Scope: ".$oObjectSet->Count()."; Related objects: ".implode(', ', $aStats); + } + else + { + $oResult->message = "Nothing found"; + } break; default: diff --git a/webservices/itoprest.examples.php b/webservices/itoprest.examples.php index 733db94d5..7d4d6b542 100644 --- a/webservices/itoprest.examples.php +++ b/webservices/itoprest.examples.php @@ -150,6 +150,13 @@ $aOperations = array( ), 'output_fields' => 'id, friendlyname, title, contacts_list', // list of fields to show in the results (* or a,b,c) ), + array( + 'operation' => 'core/get_related', // operation code + 'class' => 'Server', + 'key' => 'SELECT Server', + 'relation' => 'impacts', // relation code + 'depth' => 4, // max recursion depth + ), ); $sUrl = "http://localhost/rest-services/webservices/rest.php?version=1.0";