diff --git a/core/config.class.inc.php b/core/config.class.inc.php index 4a113be59..5b04fe61d 100644 --- a/core/config.class.inc.php +++ b/core/config.class.inc.php @@ -70,6 +70,7 @@ class Config protected $m_aAppModules; protected $m_aDataModels; + protected $m_aWebServiceCategories; protected $m_aAddons; protected $m_aDictionaries; @@ -281,6 +282,9 @@ class Config 'core/trigger.class.inc.php', ); $this->m_aDataModels = array(); + $this->m_aWebServiceCategories = array( + 'webservices/webservices.basic.php', + ); $this->m_aAddons = array( // Default AddOn, always present can be moved to an official iTop Module later if needed 'user rights' => 'addons/userrights/userrightsprofile.class.inc.php', @@ -405,6 +409,7 @@ class Config } $this->m_aAppModules = $MyModules['application']; $this->m_aDataModels = $MyModules['business']; + $this->m_aWebServiceCategories = $MyModules['webservices']; $this->m_aAddons = $MyModules['addons']; $this->m_aDictionaries = $MyModules['dictionaries']; @@ -489,6 +494,15 @@ class Config $this->m_aDataModels = $aDataModels; } + public function GetWebServiceCategories() + { + return $this->m_aWebServiceCategories; + } + public function SetWebServiceCategories($aWebServiceCategories) + { + $this->m_aWebServiceCategories = $aWebServiceCategories; + } + public function GetAddons() { return $this->m_aAddons; @@ -856,6 +870,12 @@ class Config fwrite($hFile, "\t\t'$sFile',\n"); } fwrite($hFile, "\t),\n"); + fwrite($hFile, "\t'webservices' => array (\n"); + foreach($this->m_aWebServiceCategories as $sFile) + { + fwrite($hFile, "\t\t'$sFile',\n"); + } + fwrite($hFile, "\t),\n"); fwrite($hFile, "\t'addons' => array (\n"); foreach($this->m_aAddons as $sKey => $sFile) { diff --git a/core/dbobjectset.class.php b/core/dbobjectset.class.php index 979826c5b..a55e1172f 100644 --- a/core/dbobjectset.class.php +++ b/core/dbobjectset.class.php @@ -158,6 +158,30 @@ class DBObjectSet return $aRet; } + public function ToArrayOfValues() + { + if (!$this->m_bLoaded) $this->Load(); + + $aRet = array(); + foreach($this->m_aData as $iRow => $aObjects) + { + foreach($aObjects as $sClassAlias => $oObject) + { + $aRet[$iRow][$sClassAlias.'.'.'id'] = $oObject->GetKey(); + $sClass = get_class($oObject); + foreach(MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef) + { + if ($oAttDef->IsScalar()) + { + $sAttName = $sClassAlias.'.'.$sAttCode; + $aRet[$iRow][$sAttName] = $oObject->Get($sAttCode); + } + } + } + } + return $aRet; + } + public function GetColumnAsArray($sAttCode, $bWithId = true) { $aRet = array(); diff --git a/core/metamodel.class.php b/core/metamodel.class.php index c266b0d64..26c8f6089 100644 --- a/core/metamodel.class.php +++ b/core/metamodel.class.php @@ -3299,6 +3299,10 @@ abstract class MetaModel { self::Plugin($sConfigFile, 'business', $sToInclude); } + foreach (self::$m_oConfig->GetWebServiceCategories() as $sModule => $sToInclude) + { + self::Plugin($sConfigFile, 'webservice', $sToInclude); + } foreach (self::$m_oConfig->GetAddons() as $sModule => $sToInclude) { self::Plugin($sConfigFile, 'addons', $sToInclude); diff --git a/setup/index.php b/setup/index.php index 226238472..152dcc05c 100644 --- a/setup/index.php +++ b/setup/index.php @@ -668,23 +668,38 @@ function BuildConfig(SetupWebpage $oP, Config &$oConfig, $aParamValues) $aAddOns = $oConfig->GetAddOns(); $aAppModules = $oConfig->GetAppModules(); $aDataModels = $oConfig->GetDataModels(); + $aWebServiceCategories = $oConfig->GetWebServiceCategories(); $aDictionaries = $oConfig->GetDictionaries(); // Merge the values with the ones provided by the modules // Make sure when don't load the same file twice... foreach($aParamValues['module'] as $sModuleId) { $oP->log('Installed iTop module: '. $sModuleId); - $aDataModels = array_unique(array_merge($aDataModels, $aAvailableModules[$sModuleId]['datamodel'])); - $aDictionaries = array_unique(array_merge($aDictionaries, $aAvailableModules[$sModuleId]['dictionary'])); - foreach($aAvailableModules[$sModuleId]['settings'] as $sProperty => $value) + if (isset($aAvailableModules[$sModuleId]['datamodel'])) { - list($sName, $sVersion) = GetModuleName($sModuleId); - $oConfig->SetModuleSetting($sName, $sProperty, $value); + $aDataModels = array_unique(array_merge($aDataModels, $aAvailableModules[$sModuleId]['datamodel'])); + } + if (isset($aAvailableModules[$sModuleId]['webservice'])) + { + $aWebServiceCategories = array_unique(array_merge($aWebServiceCategories, $aAvailableModules[$sModuleId]['webservice'])); + } + if (isset($aAvailableModules[$sModuleId]['dictionary'])) + { + $aDictionaries = array_unique(array_merge($aDictionaries, $aAvailableModules[$sModuleId]['dictionary'])); + } + if (isset($aAvailableModules[$sModuleId]['settings'])) + { + foreach($aAvailableModules[$sModuleId]['settings'] as $sProperty => $value) + { + list($sName, $sVersion) = GetModuleName($sModuleId); + $oConfig->SetModuleSetting($sName, $sProperty, $value); + } } } $oConfig->SetAddOns($aAddOns); $oConfig->SetAppModules($aAppModules); $oConfig->SetDataModels($aDataModels); + $oConfig->SetWebServiceCategories($aWebServiceCategories); $oConfig->SetDictionaries($aDictionaries); } diff --git a/setup/setuppage.class.inc.php b/setup/setuppage.class.inc.php index 7834c5549..3e62f2764 100644 --- a/setup/setuppage.class.inc.php +++ b/setup/setuppage.class.inc.php @@ -259,7 +259,7 @@ table.formTable { static $m_aModules = array(); // All the entries below are list of file paths relative to the module directory - static $m_aFilesList = array('datamodel', 'dictionary', 'data.struct', 'data.sample'); + static $m_aFilesList = array('datamodel', 'webservice', 'dictionary', 'data.struct', 'data.sample'); static $m_sModulePath = null; public function SetModulePath($sModulePath) @@ -281,11 +281,14 @@ table.formTable { foreach(self::$m_aFilesList as $sAttribute) { - // All the items below are list of files, that are relative to the current file - // being loaded, let's update their path to store path relative to the application directory - foreach(self::$m_aModules[$sId][$sAttribute] as $idx => $sRelativePath) + if (isset(self::$m_aModules[$sId][$sAttribute])) { + // All the items below are list of files, that are relative to the current file + // being loaded, let's update their path to store path relative to the application directory + foreach(self::$m_aModules[$sId][$sAttribute] as $idx => $sRelativePath) + { self::$m_aModules[$sId][$sAttribute][$idx] = self::$m_sModulePath.'/'.$sRelativePath; + } } } } diff --git a/test/testlist.inc.php b/test/testlist.inc.php index d54682ec1..a15ac5992 100644 --- a/test/testlist.inc.php +++ b/test/testlist.inc.php @@ -1612,14 +1612,17 @@ class TestImportRESTMassive extends TestImportREST // Test SOAP services /////////////////////////////////////////////////////////////////////////// -$aWebServices = array( +$aCreateTicketSpecs = array( array( + 'service_category' => 'BasicServices', 'verb' => 'GetVersion', - 'expected result' => WebServices::GetVersion(), +// 'expected result' => '1.0.1', + 'expected result' => '$ITOP_VERSION$ [dev]', 'explain result' => 'no comment!', 'args' => array(), ), array( + 'service_category' => '', 'verb' => 'CreateIncidentTicket', 'expected result' => true, 'explain result' => 'link attribute unknown + a CI not found', @@ -1656,6 +1659,7 @@ $aWebServices = array( ), ), array( + 'service_category' => '', 'verb' => 'CreateIncidentTicket', 'expected result' => true, 'explain result' => 'caller not specified', @@ -1682,6 +1686,7 @@ $aWebServices = array( ), ), array( + 'service_category' => '', 'verb' => 'CreateIncidentTicket', 'expected result' => false, 'explain result' => 'wrong class on CI to attach', @@ -1708,6 +1713,7 @@ $aWebServices = array( ), ), array( + 'service_category' => '', 'verb' => 'CreateIncidentTicket', 'expected result' => false, 'explain result' => 'wrong search condition on CI to attach', @@ -1734,6 +1740,7 @@ $aWebServices = array( ), ), array( + 'service_category' => '', 'verb' => 'CreateIncidentTicket', 'expected result' => true, 'explain result' => 'no CI to attach (empty array)', @@ -1755,6 +1762,7 @@ $aWebServices = array( ), ), array( + 'service_category' => '', 'verb' => 'CreateIncidentTicket', 'expected result' => true, 'explain result' => 'no CI to attach (null)', @@ -1775,6 +1783,7 @@ $aWebServices = array( ), ), array( + 'service_category' => '', 'verb' => 'CreateIncidentTicket', 'expected result' => true, 'explain result' => 'caller unknown', @@ -1796,6 +1805,7 @@ $aWebServices = array( ), ), array( + 'service_category' => '', 'verb' => 'CreateIncidentTicket', 'expected result' => false, 'explain result' => 'wrong values for impact and urgency', @@ -1817,6 +1827,7 @@ $aWebServices = array( ), ), array( + 'service_category' => '', 'verb' => 'CreateIncidentTicket', 'expected result' => false, 'explain result' => 'wrong password', @@ -1838,6 +1849,7 @@ $aWebServices = array( ), ), array( + 'service_category' => '', 'verb' => 'CreateIncidentTicket', 'expected result' => false, 'explain result' => 'wrong login', @@ -1861,41 +1873,145 @@ $aWebServices = array( ); -class TestSoap extends TestSoapWebService +$aManageCloudUsersSpecs = array( + array( + 'service_category' => '', + 'verb' => 'SearchObjects', + 'expected result' => false, + 'explain result' => 'wrong OQL', + 'args' => array( + 'admin', /* sLogin */ + 'admin', /* sPassword */ + 'SELECT ThisClassDoesNotExist', /* sOQL */ + ), + ), + array( + 'service_category' => '', + 'verb' => 'SearchObjects', + 'expected result' => true, + 'explain result' => 'ok', + 'args' => array( + 'admin', /* sLogin */ + 'admin', /* sPassword */ + 'SELECT Organization', /* sOQL */ + ), + ), + array( + 'service_category' => 'CloudUsersManagementService', + 'verb' => 'CreateAccount', + 'expected result' => true, + 'explain result' => 'ok', + 'args' => array( + 'admin', /* sAdminLogin */ + 'admin', /* sAdminPassword */ + 'andros@combodo.com', /* sLogin */ + 'André', /* sFirstName */ + 'Dupont', /* sLastName */ + 1, /* iOrgId */ + 'FR FR', /* sLanguage */ + array( + array( + new SOAPKeyValue('profile_id', '2'), + new SOAPKeyValue('reason', 'whynot'), + ), + array( + new SOAPKeyValue('profile_id', '3'), + new SOAPKeyValue('reason', 'because'), + ), + ), /* aProfiles (array of key/value pairs) */ + array( + ), /* aAllowedOrgs (array of key/value pairs) */ + 'comment on the creation operation', /* sComment */ + ), + ), + array( + 'service_category' => 'CloudUsersManagementService', + 'verb' => 'ModifyAccount', + 'expected result' => true, + 'explain result' => 'ok', + 'args' => array( + 'admin', /* sAdminLogin */ + 'admin', /* sAdminPassword */ + 'andros@combodo.com', /* sLogin */ + 'nono', /* sFirstName */ + 'robot', /* sLastName */ + 2, /* iOrgId */ + 'EN US', /* sLanguage */ + array( + array( + new SOAPKeyValue('profile_id', '3'), + new SOAPKeyValue('reason', 'because'), + ), + ), /* aProfiles (array of key/value pairs) */ + array( + ), /* aAllowedOrgs (array of key/value pairs) */ + 'comment on the modify operation', /* sComment */ + ), + ), + array( + 'service_category' => 'CloudUsersManagementService', + 'verb' => 'DeleteAccount', + 'expected result' => true, + 'explain result' => '', + 'args' => array( + 'admin', /* sAdminLogin */ + 'admin', /* sAdminPassword */ + 'andros@combodo.com', /* sLogin */ + 'comment on the deletion operation', /* sComment */ + ), + ), + array( + 'service_category' => 'CloudUsersManagementService', + 'verb' => 'DeleteAccount', + 'expected result' => false, + 'explain result' => 'wrong login', + 'args' => array( + 'admin', /* sAdminLogin */ + 'admin', /* sAdminPassword */ + 'taratatata@sdf.com', /* sLogin */ + 'comment on the deletion operation', /* sComment */ + ), + ), +); + +abstract class TestSoap extends TestSoapWebService { static public function GetName() {return 'Test SOAP';} static public function GetDescription() {return 'Do basic stuff to test the SOAP capability';} + protected $m_aTestSpecs; + protected function DoExecute() { echo "
Note: You may also want to try the sample SOAP client itopsoap.examples.php
\n"; - global $aSOAPMapping; + $aSOAPMapping = SOAPMapping::GetMapping(); // this file is generated dynamically with location = here $sWsdlUri = 'http'.(isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS']!='off') ? 's' : '').'://'.$_SERVER['SERVER_NAME'].':'.$_SERVER['SERVER_PORT'].dirname($_SERVER['SCRIPT_NAME']).'/../webservices/itop.wsdl.php'; ini_set("soap.wsdl_cache_enabled","0"); - $this->m_SoapClient = new SoapClient - ( - $sWsdlUri, - array( - 'classmap' => $aSOAPMapping, - 'trace' => 1, - ) - ); - if (false) - { - self::DumpVariable($this->m_SoapClient->__getTypes()); - } - - global $aWebServices; - foreach ($aWebServices as $iPos => $aWebService) + foreach ($this->m_aTestSpecs as $iPos => $aWebService) { echo "{$aWebService['explain result']}
\n"; + $sWsdlUriForService = $sWsdlUri.'?service_category='.$aWebService['service_category']; + $this->m_SoapClient = new SoapClient + ( + $sWsdlUriForService, + array( + 'classmap' => $aSOAPMapping, + 'trace' => 1, + ) + ); + + if (false) + { + self::DumpVariable($this->m_SoapClient->__getTypes()); + } + try { $oRes = call_user_func_array(array($this->m_SoapClient, $aWebService['verb']), $aWebService['args']); @@ -1921,6 +2037,10 @@ class TestSoap extends TestSoapWebService { $res = $oRes->status; } + elseif ($oRes instanceof SOAPSimpleResult) + { + $res = $oRes->status; + } else { $res = $oRes; @@ -1937,20 +2057,23 @@ class TestSoap extends TestSoapWebService } } -class TestWebServicesDirect extends TestBizModel +abstract class TestSoapDirect extends TestBizModel { static public function GetName() {return 'Test web services locally';} static public function GetDescription() {return 'Invoke the service directly (troubleshooting)';} static public function GetConfigFile() {return '/config-itop.php';} + protected $m_aTestSpecs; + protected function DoExecute() { - $oWebServices = new WebServices(); - - global $aWebServices; - foreach ($aWebServices as $iPos => $aWebService) + foreach ($this->m_aTestSpecs as $iPos => $aWebService) { + $sServiceClass = $aWebService['service_category']; + if (empty($sServiceClass)) $sServiceClass = 'BasicServices'; + $oWebServices = new $sServiceClass(); + echo "{$aWebService['explain result']}
\n"; $oRes = call_user_func_array(array($oWebServices, $aWebService['verb']), $aWebService['args']); @@ -1960,6 +2083,10 @@ class TestWebServicesDirect extends TestBizModel { $res = $oRes->status; } + elseif ($oRes instanceof SOAPSimpleResult) + { + $res = $oRes->status; + } else { $res = $oRes; @@ -1977,6 +2104,59 @@ class TestWebServicesDirect extends TestBizModel } } +class TestSoap_Tickets extends TestSoap +{ + static public function GetName() {return 'Test SOAP - create ticket';} + + protected function DoExecute() + { + global $aCreateTicketSpecs; + $this->m_aTestSpecs = $aCreateTicketSpecs; + return parent::DoExecute(); + } +} + +class TestSoapDirect_Tickets extends TestSoapDirect +{ + static public function GetName() {return 'Test SOAP without SOAP - create ticket';} + + protected function DoExecute() + { + global $aCreateTicketSpecs; + $this->m_aTestSpecs = $aCreateTicketSpecs; + return parent::DoExecute(); + } +} + + +class TestSoap_ManageCloudUsers extends TestSoap +{ + static public function GetName() {return 'Test SOAP - manage Cloud Users';} + + protected function DoExecute() + { + global $aManageCloudUsersSpecs; + $this->m_aTestSpecs = $aManageCloudUsersSpecs; + return parent::DoExecute(); + } +} + +class TestSoapDirect_ManageCloudUsers extends TestSoapDirect +{ + static public function GetName() {return 'Test SOAP without SOAP - manage Cloud Users';} + + protected function DoExecute() + { + global $aManageCloudUsersSpecs; + $this->m_aTestSpecs = $aManageCloudUsersSpecs; + return parent::DoExecute(); + } +} + + +////////////////////// End of SOAP TESTS + + class TestTriggerAndEmail extends TestBizModel { static public function GetName() {return 'Test trigger and email';} diff --git a/webservices/itop.wsdl.php b/webservices/itop.wsdl.php index d36e227e3..aa71bb405 100644 --- a/webservices/itop.wsdl.php +++ b/webservices/itop.wsdl.php @@ -23,17 +23,53 @@ * @license http://www.opensource.org/licenses/gpl-3.0.html LGPL */ -// This is to make sure that the client will accept it.... +if (isset($_REQUEST['debug'])) +{ + if ($_REQUEST['debug'] == 'text') + { + header('Content-Type: text/plain; charset=UTF-8'); + } + else + { + header('Content-Type: application/xml; charset=UTF-8'); + } +} +else +{ + // This is to make sure that the client will accept it.... + // + header('Content-Type: application/xml; charset=UTF-8'); + ////header('Content-Disposition: attachment; filename="itop.wsdl"'); + header('Content-Disposition: online; filename="itop.wsdl"'); +} + +require_once('../approot.inc.php'); +require_once(APPROOT.'webservices/webservices.class.inc.php'); +require_once(APPROOT.'core/config.class.inc.php'); + +// Load the modules installed and enabled // -header('Content-Type: application/xml; charset=UTF-8'); -//header('Content-Disposition: attachment; filename="itop.wsdl"'); -header('Content-Disposition: online; filename="itop.wsdl"'); +$oConfig = new Config(APPROOT.'config-itop.php'); +$aFiles = $oConfig->GetWebServiceCategories(); +foreach ($aFiles as $sFile) +{ + require_once(APPROOT.$sFile); +} -$sMyWsdl = './itop.wsdl.tpl'; - -$sRawFile = file_get_contents($sMyWsdl); +if (isset($_REQUEST['service_category']) && (!empty($_REQUEST['service_category']))) +{ + $sRawFile = WebServicesBase::GetWSDLContents($_REQUEST['service_category']); +} +else +{ + $sRawFile = WebServicesBase::GetWSDLContents(); +} $sServerURI = 'http'.((isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS']!='off')) ? 's' : '').'://'.$_SERVER['SERVER_NAME'].':'.$_SERVER['SERVER_PORT'].dirname($_SERVER['SCRIPT_NAME']).'/soapserver.php'; +if (isset($_REQUEST['service_category']) && (!empty($_REQUEST['service_category']))) +{ + $sServerURI .= "?service_category=".$_REQUEST['service_category']; +} $sFinalFile = str_replace( '___SOAP_SERVER_URI___', diff --git a/webservices/itop.wsdl.tpl b/webservices/itop.wsdl.tpl index f4a2b4051..8d6ddf6ca 100644 --- a/webservices/itop.wsdl.tpl +++ b/webservices/itop.wsdl.tpl @@ -161,6 +161,14 @@SearchObjects() returned:\n"; + if ($oRes->status) + { + $aResults = $oRes->result; + + echo "
| ".$aKeyValuePair->key." | \n"; + } + echo "
|---|
| ".$aKeyValuePair->value." | \n"; + } + echo "
SearchObjects() failed with message: $sErrorMsg
\n"; + //echo "\n"; + //print_r($oRes); + //echo "\n"; + } + echo "\n"; } catch(SoapFault $e) { diff --git a/webservices/itopsoaptypes.class.inc.php b/webservices/itopsoaptypes.class.inc.php index c55a8283f..5811236a3 100644 --- a/webservices/itopsoaptypes.class.inc.php +++ b/webservices/itopsoaptypes.class.inc.php @@ -107,7 +107,7 @@ class SOAPResultLog } -class SOAPResultData +class SOAPKeyValue { public $key; // string public $value; // string @@ -119,11 +119,10 @@ class SOAPResultData } } - class SOAPResultMessage { public $label; // string - public $values; // array of SOAPResultData + public $values; // array of SOAPKeyValue public function __construct($sLabel, $aValues) { @@ -151,17 +150,38 @@ class SOAPResult } } -$aSOAPMapping = array( - 'SearchCondition' => 'SOAPSearchCondition', - 'ExternalKeySearch' => 'SOAPExternalKeySearch', - 'AttributeValue' => 'SOAPAttributeValue', - 'LinkCreationSpec' => 'SOAPLinkCreationSpec', - 'LogMessage' => 'SOAPLogMessage', - 'ResultLog' => 'SOAPResultLog', - 'ResultData' => 'SOAPResultData', - 'ResultMessage' => 'SOAPResultMessage', - 'Result' => 'SOAPResult', -); +class SOAPSimpleResult +{ + public $status; // boolean + public $message; // string + public function __construct($bStatus, $sMessage) + { + $this->status = $bStatus; + $this->message = $sMessage; + } +} + + +class SOAPMapping +{ + static function GetMapping() + { + $aSOAPMapping = array( + 'SearchCondition' => 'SOAPSearchCondition', + 'ExternalKeySearch' => 'SOAPExternalKeySearch', + 'AttributeValue' => 'SOAPAttributeValue', + 'LinkCreationSpec' => 'SOAPLinkCreationSpec', + 'KeyValue' => 'SOAPKeyValue', + 'LogMessage' => 'SOAPLogMessage', + 'ResultLog' => 'SOAPResultLog', + 'ResultData' => 'SOAPKeyValue', + 'ResultMessage' => 'SOAPResultMessage', + 'Result' => 'SOAPResult', + 'SimpleResult' => 'SOAPSimpleResult', + ); + return $aSOAPMapping; + } +} ?> diff --git a/webservices/soapserver.php b/webservices/soapserver.php index fb7515924..28d67c794 100644 --- a/webservices/soapserver.php +++ b/webservices/soapserver.php @@ -30,14 +30,17 @@ require_once('../approot.inc.php'); require_once(APPROOT.'/application/application.inc.php'); require_once(APPROOT.'/application/startup.inc.php'); -require('./webservices.class.inc.php'); - // this file is generated dynamically with location = here $sWsdlUri = 'http'.((isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS']!='off')) ? 's' : '').'://'.$_SERVER['SERVER_NAME'].':'.$_SERVER['SERVER_PORT'].dirname($_SERVER['SCRIPT_NAME']).'/../webservices/itop.wsdl.php'; +if (isset($_REQUEST['service_category']) && (!empty($_REQUEST['service_category']))) +{ + $sWsdlUri .= "?service_category=".$_REQUEST['service_category']; +} ini_set("soap.wsdl_cache_enabled","0"); +$aSOAPMapping = SOAPMapping::GetMapping(); $oSoapServer = new SoapServer ( $sWsdlUri, @@ -46,7 +49,28 @@ $oSoapServer = new SoapServer ) ); // $oSoapServer->setPersistence(SOAP_PERSISTENCE_SESSION); -$oSoapServer->setClass('WebServices', null); +if (isset($_REQUEST['service_category']) && (!empty($_REQUEST['service_category']))) +{ + $sServiceClass = $_REQUEST['service_category']; + if (!class_exists($sServiceClass)) + { + // not a valid class name (not a PHP class at all) + throw new SoapFault("iTop SOAP server", "Invalid argument service_category: '$sServiceClass' is not a PHP class"); + } + elseif (!is_subclass_of($sServiceClass, 'WebServicesBase')) + { + // not a valid class name (not deriving from WebServicesBase) + throw new SoapFault("iTop SOAP server", "Invalid argument service_category: '$sServiceClass' is not derived from WebServicesBase"); + } + else + { + $oSoapServer->setClass($sServiceClass, null); + } +} +else +{ + $oSoapServer->setClass('BasicServices', null); +} if ($_SERVER["REQUEST_METHOD"] == "POST") { @@ -59,9 +83,25 @@ else echo "
Here the WSDL file
"; + + echo "You may also want to try the following service categories: "; + echo "