Sfoglia il codice sorgente

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

git-svn-id: http://svn.code.sf.net/p/itop/code/trunk@2666 a333f486-631f-4898-b8df-5754b55c2be0
dflaven 12 anni fa
parent
commit
0754256049
1 ha cambiato i file con 89 aggiunte e 0 eliminazioni
  1. 89 0
      core/restservices.class.inc.php

+ 89 - 0
core/restservices.class.inc.php

@@ -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);
+			}
+		}
+	}
 }