First (draft) version of the get_related verb for the REST API.

SVN:trunk[2666]
This commit is contained in:
Denis Flaven
2013-04-02 09:42:26 +00:00
parent 48472b6150
commit d92b0aabee

View File

@@ -166,6 +166,26 @@ class RestResultWithObjects extends RestResult
}
}
class RestResultWithRelations extends RestResultWithObjects
{
public $relations;
public function __construct()
{
parent::__construct();
$this->relations = array();
}
public function AddRelation($sSrcKey, $sDestKey)
{
if (!array_key_exists($sSrcKey, $this->relations))
{
$this->relations[$sSrcKey] = array();
}
$this->relations[$sSrcKey][] = $sDestKey;
}
}
/**
* Deletion result codes for a target object (either deleted or updated)
*
@@ -243,6 +263,10 @@ class CoreServices implements iRestServiceProvider
'verb' => 'core/delete',
'description' => 'Delete objects'
);
$aOps[] = array(
'verb' => 'core/get_related',
'description' => 'Get related objects through the specified relation'
);
}
return $aOps;
}
@@ -360,6 +384,37 @@ class CoreServices implements iRestServiceProvider
$this->DeleteObjects($oResult, $aObjects, $bSimulate);
break;
case 'core/get_related':
$oResult = new RestResultWithRelations();
$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');
$oObjectSet = RestUtils::GetObjectSetFromKey($sClass, $key);
while ($oObject = $oObjectSet->Fetch())
{
$aRelated = array();
$aGraph = array();
$oResult->AddObject(0, '', $oObject, $aShowFields);
$this->GetRelatedObjects($oObject, $sRelation, $iMaxRecursionDepth, $aRelated, $aGraph);
foreach($aRelated as $sClass => $aObjects)
{
foreach($aObjects as $oRelatedObj)
{
$oResult->AddObject(0, '', $oRelatedObj, $aShowFields);
}
}
foreach($aGraph as $sSrcKey => $sDestKey)
{
$oResult->AddRelation($sSrcKey, $sDestKey);
}
}
$oResult->message = "Found: ".$oObjectSet->Count();
break;
default:
// unknown operation: handled at a higher level
}
@@ -492,4 +547,38 @@ class CoreServices implements iRestServiceProvider
$oResult->message = $sRes;
}
}
/**
* Helper function to get the related objects up to the given depth along with the "graph" of the relation
* @param DBObject $oObject Starting point of the computation
* @param string $sRelation Code of the relation (i.e; 'impact', 'depends on'...)
* @param integer $iMaxRecursionDepth Maximum level of recursion
* @param Hash $aRelated Two dimensions hash of the already related objects: array( 'class' => array(key => ))
* @param Hash $aGraph Hash array for the topology of the relation: source => related: array('class:key' => array( DBObjects ))
* @param integer $iRecursionDepth Current level of recursion
*/
protected function GetRelatedObjects(DBObject $oObject, $sRelation, $iMaxRecursionDepth, &$aRelated, &$aGraph, $iRecursionDepth = 1)
{
// Avoid loops
if ((array_key_exists(get_class($oObject), $aRelated)) && (array_key_exists($oObject->GetKey(), $aRelated[get_class($oObject)]))) return;
// Stop at maximum recursion level
if ($iRecursionDepth > $iMaxRecursionDepth) return;
$sSrcKey = get_class($oObject).'::'.$oObject->GetKey();
$aNewRelated = array();
$oObject->GetRelatedObjects($sRelation, 1, $aNewRelated);
foreach($aNewRelated as $sClass => $aObjects)
{
if (!array_key_exists($sSrcKey, $aGraph))
{
$aGraph[$sSrcKey] = array();
}
foreach($aObjects as $oRelatedObject)
{
$aRelated[$sClass][$oRelatedObject->GetKey()] = $oRelatedObject;
$aGraph[$sSrcKey][] = get_class($oRelatedObject).'::'.$oRelatedObject->GetKey();
$this->GetRelatedObjects($oRelatedObject, $sRelation, $iMaxRecursionDepth, $aRelated, $aGraph, $iRecursionDepth+1);
}
}
}
}