123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258 |
- <?php
- // Copyright (C) 2013 Combodo SARL
- //
- // This file is part of iTop.
- //
- // iTop is free software; you can redistribute it and/or modify
- // it under the terms of the GNU Affero General Public License as published by
- // the Free Software Foundation, either version 3 of the License, or
- // (at your option) any later version.
- //
- // iTop is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- // GNU Affero General Public License for more details.
- //
- // You should have received a copy of the GNU Affero General Public License
- // along with iTop. If not, see <http://www.gnu.org/licenses/>
- /**
- * REST/json services
- *
- * Definition of common structures + the very minimum service provider (manage objects)
- *
- * @package REST Services
- * @copyright Copyright (C) 2013 Combodo SARL
- * @license http://opensource.org/licenses/AGPL-3.0
- * @api
- */
- /**
- * Element of the response formed by RestResultWithObjects
- *
- * @package REST Services
- */
- class ObjectResult
- {
- public $code;
- public $message;
- public $fields;
-
- /**
- * Default constructor
- */
- public function __construct()
- {
- $this->code = RestResult::OK;
- $this->message = '';
- $this->fields = array();
- }
- /**
- * Helper to make an output value for a given attribute
- *
- * @param DBObject $oObject The object being reported
- * @param string $sAttCode The attribute code (must be valid)
- * @return string A scalar representation of the value
- */
- protected function MakeResultValue(DBObject $oObject, $sAttCode)
- {
- if ($sAttCode == 'id')
- {
- $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;
- }
- }
- elseif ($oAttDef->IsExternalKey())
- {
- $value = $oObject->Get($sAttCode);
- }
- else
- {
- // Still to be refined...
- $value = $oObject->GetEditValue($sAttCode);
- }
- }
- return $value;
- }
- /**
- * Report the value for the given object attribute
- *
- * @param DBObject $oObject The object being reported
- * @param string $sAttCode The attribute code (must be valid)
- * @return void
- */
- public function AddField(DBObject $oObject, $sAttCode)
- {
- $this->fields[$sAttCode] = $this->MakeResultValue($oObject, $sAttCode);
- }
- }
- /**
- * REST response for services managing objects. Derive this structure to add information and/or constants
- *
- * @package Extensibility
- * @package REST Services
- * @api
- */
- class RestResultWithObjects extends RestResult
- {
- public $objects;
- /**
- * Report the given object
- *
- * @param int An error code (RestResult::OK is no issue has been found)
- * @param string $sMessage Description of the error if any, an empty string otherwise
- * @param DBObject $oObject The object being reported
- * @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)
- {
- $oObjRes = new ObjectResult();
- $oObjRes->code = $iCode;
- $oObjRes->message = $sMessage;
- if ($oObject)
- {
- foreach ($aFields as $sAttCode)
- {
- $oObjRes->AddField($oObject, $sAttCode);
- }
- }
- $this->objects[] = $oObjRes;
- }
- }
- /**
- * Implementation of core REST services (create/get/update... objects)
- *
- * @package Core
- */
- class CoreServices implements iRestServiceProvider
- {
- /**
- * Enumerate services delivered by this class
- *
- * @param string $sVersion The version (e.g. 1.0) supported by the services
- * @return array An array of hash 'verb' => verb, 'description' => description
- */
- public function ListOperations($sVersion)
- {
- $aOps = array();
- if ($sVersion == '1.0')
- {
- $aOps[] = array(
- 'verb' => 'core/create',
- 'description' => 'Create an object'
- );
- $aOps[] = array(
- 'verb' => 'core/update',
- 'description' => 'Update an object'
- );
- $aOps[] = array(
- 'verb' => 'core/get',
- 'description' => 'Search for objects'
- );
- }
- return $aOps;
- }
- /**
- * Enumerate services delivered by this class
- * @param string $sVersion The version (e.g. 1.0) supported by the services
- * @return RestResult The standardized result structure (at least a message)
- * @throws Exception in case of internal failure.
- */
- public function ExecOperation($sVersion, $sVerb, $aParams)
- {
- $oResult = new RestResultWithObjects();
- switch ($sVerb)
- {
- case 'core/create':
- RestUtils::InitTrackingComment($aParams);
- $sClass = RestUtils::GetClass($aParams, 'class');
- $aFields = RestUtils::GetMandatoryParam($aParams, 'fields');
- $aShowFields = RestUtils::GetFieldList($sClass, $aParams, 'output_fields');
-
- $oObject = RestUtils::MakeObjectFromFields($sClass, $aFields);
- $oObject->DBInsert();
-
- $oResult->AddObject(0, 'created', $oObject, $aShowFields);
- break;
-
- case 'core/update':
- RestUtils::InitTrackingComment($aParams);
- $sClass = RestUtils::GetClass($aParams, 'class');
- $key = RestUtils::GetMandatoryParam($aParams, 'key');
- $aFields = RestUtils::GetMandatoryParam($aParams, 'fields');
- $aShowFields = RestUtils::GetFieldList($sClass, $aParams, 'output_fields');
-
- $oObject = RestUtils::FindObjectFromKey($sClass, $key);
- RestUtils::UpdateObjectFromFields($oObject, $aFields);
- $oObject->DBUpdate();
-
- $oResult->AddObject(0, 'updated', $oObject, $aShowFields);
- break;
-
- case 'core/get':
- $sClass = RestUtils::GetClass($aParams, 'class');
- $key = RestUtils::GetMandatoryParam($aParams, 'key');
- $aShowFields = RestUtils::GetFieldList($sClass, $aParams, 'output_fields');
-
- $oObjectSet = RestUtils::GetObjectSetFromKey($sClass, $key);
- while ($oObject = $oObjectSet->Fetch())
- {
- $oResult->AddObject(0, '', $oObject, $aShowFields);
- }
- $oResult->message = "Found: ".$oObjectSet->Count();
- break;
-
- default:
- // unknown operation: handled at a higher level
- }
- return $oResult;
- }
- }
|