summaryrefslogtreecommitdiff
path: root/framework/Web/Services
diff options
context:
space:
mode:
authorFabio Bas <ctrlaltca@gmail.com>2015-01-20 22:12:46 +0100
committerFabio Bas <ctrlaltca@gmail.com>2015-01-20 22:12:46 +0100
commit7254793d2bbe3f2f3d87d97172c54a54deea0a3a (patch)
tree696f734b5f0fad620f459a4639e269bffad4444d /framework/Web/Services
parent6a77820f00da900f2355e16ef9aa77cd132fb423 (diff)
One class per file: framework/Web/Services
Diffstat (limited to 'framework/Web/Services')
-rw-r--r--framework/Web/Services/IFeedContentProvider.php49
-rw-r--r--framework/Web/Services/TFeedService.php40
-rw-r--r--framework/Web/Services/TJsonResponse.php57
-rw-r--r--framework/Web/Services/TJsonRpcProtocol.php180
-rw-r--r--framework/Web/Services/TJsonService.php50
-rw-r--r--framework/Web/Services/TPageConfiguration.php362
-rw-r--r--framework/Web/Services/TPageService.php355
-rw-r--r--framework/Web/Services/TRpcApiProvider.php86
-rw-r--r--framework/Web/Services/TRpcException.php31
-rw-r--r--framework/Web/Services/TRpcProtocol.php98
-rw-r--r--framework/Web/Services/TRpcServer.php78
-rw-r--r--framework/Web/Services/TRpcService.php548
-rw-r--r--framework/Web/Services/TSoapServer.php345
-rw-r--r--framework/Web/Services/TSoapService.php337
-rw-r--r--framework/Web/Services/TXmlRpcProtocol.php131
15 files changed, 1423 insertions, 1324 deletions
diff --git a/framework/Web/Services/IFeedContentProvider.php b/framework/Web/Services/IFeedContentProvider.php
new file mode 100644
index 00000000..0711330c
--- /dev/null
+++ b/framework/Web/Services/IFeedContentProvider.php
@@ -0,0 +1,49 @@
+<?php
+/**
+ * TFeedService and TFeed class file
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @author Knut Urdalen <knut.urdalen@gmail.com>
+ * @link http://www.pradosoft.com
+ * @copyright Copyright &copy; 2005-2014 PradoSoft
+ * @license http://www.pradosoft.com/license/
+ * @version $Id$
+ * @package System.Web.Services
+ */
+
+/**
+ * IFeedContentProvider interface.
+ *
+ * IFeedContentProvider interface must be implemented by a feed class who
+ * provides feed content.
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @author Knut Urdalen <knut.urdalen@gmail.com>
+ * @package System.Web.Services
+ * @since 3.1
+ */
+interface IFeedContentProvider
+{
+ /**
+ * Initializes the feed content provider.
+ * This method is invoked (before {@link getFeedContent})
+ * when the feed provider is requested by a user.
+ * @param TXmlElement configurations specified within the &lt;feed&gt; element
+ * corresponding to this feed provider when configuring {@link TFeedService}.
+ */
+ public function init($config);
+ /**
+ * @return string feed content in proper XML format
+ */
+ public function getFeedContent();
+ /**
+ * Sets the content type of the feed content to be sent.
+ * Some examples are:
+ * RSS 1.0 feed: application/rdf+xml
+ * RSS 2.0 feed: application/rss+xml or application/xml or text/xml
+ * ATOM feed: application/atom+xml
+ * @return string the content type for the feed content.
+ * @since 3.1.1
+ */
+ public function getContentType();
+} \ No newline at end of file
diff --git a/framework/Web/Services/TFeedService.php b/framework/Web/Services/TFeedService.php
index 75775f49..2791c1c4 100644
--- a/framework/Web/Services/TFeedService.php
+++ b/framework/Web/Services/TFeedService.php
@@ -146,42 +146,4 @@ class TFeedService extends TService
else
throw new THttpException(404,'feedservice_feed_unknown',$id);
}
-}
-
-/**
- * IFeedContentProvider interface.
- *
- * IFeedContentProvider interface must be implemented by a feed class who
- * provides feed content.
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @author Knut Urdalen <knut.urdalen@gmail.com>
- * @package System.Web.Services
- * @since 3.1
- */
-interface IFeedContentProvider
-{
- /**
- * Initializes the feed content provider.
- * This method is invoked (before {@link getFeedContent})
- * when the feed provider is requested by a user.
- * @param TXmlElement configurations specified within the &lt;feed&gt; element
- * corresponding to this feed provider when configuring {@link TFeedService}.
- */
- public function init($config);
- /**
- * @return string feed content in proper XML format
- */
- public function getFeedContent();
- /**
- * Sets the content type of the feed content to be sent.
- * Some examples are:
- * RSS 1.0 feed: application/rdf+xml
- * RSS 2.0 feed: application/rss+xml or application/xml or text/xml
- * ATOM feed: application/atom+xml
- * @return string the content type for the feed content.
- * @since 3.1.1
- */
- public function getContentType();
-}
-
+} \ No newline at end of file
diff --git a/framework/Web/Services/TJsonResponse.php b/framework/Web/Services/TJsonResponse.php
new file mode 100644
index 00000000..496229f5
--- /dev/null
+++ b/framework/Web/Services/TJsonResponse.php
@@ -0,0 +1,57 @@
+<?php
+/**
+ * TJsonService and TJsonResponse class file.
+ *
+ * @author Wei Zhuo <weizhuo[at]gamil[dot]com>
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright &copy; 2005-2014 PradoSoft
+ * @license http://www.pradosoft.com/license/
+ * @package System.Web.Services
+ */
+
+/**
+ * TJsonResponse Class
+ *
+ * TJsonResponse is the base class for all JSON response provider classes.
+ *
+ * Derived classes must implement {@link getJsonContent()} to return
+ * an object or literals to be converted to JSON format. The response
+ * will be empty if the returned content is null.
+ *
+ * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
+ * @package System.Web.Services
+ * @since 3.1
+ */
+abstract class TJsonResponse extends TApplicationComponent
+{
+ private $_id='';
+
+ /**
+ * Initializes the feed.
+ * @param TXmlElement configurations specified in {@link TJsonService}.
+ */
+ public function init($config)
+ {
+ }
+
+ /**
+ * @return string ID of this response
+ */
+ public function getID()
+ {
+ return $this->_id;
+ }
+
+ /**
+ * @param string ID of this response
+ */
+ public function setID($value)
+ {
+ $this->_id=$value;
+ }
+
+ /**
+ * @return object json response content, null to suppress output.
+ */
+ abstract public function getJsonContent();
+} \ No newline at end of file
diff --git a/framework/Web/Services/TJsonRpcProtocol.php b/framework/Web/Services/TJsonRpcProtocol.php
new file mode 100644
index 00000000..b3196b13
--- /dev/null
+++ b/framework/Web/Services/TJsonRpcProtocol.php
@@ -0,0 +1,180 @@
+<?php
+/**
+ * @author Robin J. Rogge <rrogge@bigpoint.net>
+ * @link http://www.pradosoft.com/
+ * @copyright 2010 Bigpoint GmbH
+ * @license http://www.pradosoft.com/license/
+ * @version $Id$
+ * @since 3.2
+ * @package System.Web.Services
+ */
+
+/**
+ * TJsonRpcProtocol class
+ *
+ * TJsonRpcProtocol is a class that implements JSON-Rpc protocol in {@link TRpcService}.
+ * Both version 1.0 and 2.0 of the specification are implemented, and the server will try
+ * to answer using the same version of the protocol used by the requesting client.
+ *
+ * @author Robin J. Rogge <rrogge@bigpoint.net>
+ * @author Fabio Bas <ctrlaltca@gmail.com>
+ * @version $Id$
+ * @package System.Web.Services
+ * @since 3.2
+ */
+class TJsonRpcProtocol extends TRpcProtocol
+{
+ protected $_id=null;
+ protected $_specificationVersion=1.0;
+
+ /**
+ * Handles the RPC request
+ * @param string $requestPayload
+ * @return string JSON RPC response
+ */
+ public function callMethod($requestPayload)
+ {
+ try
+ {
+ $_request = $this->decode($requestPayload);
+
+ if(isset($_request['jsonrpc']))
+ {
+ $this->_specificationVersion=$_request['jsonrpc'];
+ if($this->_specificationVersion > 2.0)
+ throw new TRpcException('Unsupported specification version', '-32600');
+ }
+
+ if(isset($_request['id']))
+ $this->_id=$_request['id'];
+
+ if(!isset($_request['method']))
+ throw new TRpcException('Missing request method', '-32600');
+
+ if(!isset($_request['params']))
+ $parameters = array();
+ else
+ $parameters = $_request['params'];
+
+ if(!is_array($parameters))
+ $parameters = array($parameters);
+
+ // a request without an id is a notification that doesn't need a response
+ if($this->_id !== null)
+ {
+ if($this->_specificationVersion==2.0)
+ {
+ return $this->encode(array(
+ 'jsonrpc' => '2.0',
+ 'id' => $this->_id,
+ 'result' => $this->callApiMethod($_request['method'], $parameters),
+ ));
+ } else {
+ return $this->encode(array(
+ 'id' => $this->_id,
+ 'result' => $this->callApiMethod($_request['method'], $_request['params']),
+ 'error' => null
+ ));
+ }
+ }
+ }
+ catch(TRpcException $e)
+ {
+ return $this->createErrorResponse($e);
+ }
+ catch(THttpException $e)
+ {
+ throw $e;
+ }
+ catch(Exception $e)
+ {
+ return $this->createErrorResponse(new TRpcException('An internal error occured', '-32603'));
+ }
+ }
+
+ /**
+ * Turns the given exception into an JSON RPC fault
+ * @param TRpcException $exception
+ * @return string JSON RPC fault
+ */
+ public function createErrorResponse(TRpcException $exception)
+ {
+ if($this->_specificationVersion==2.0)
+ {
+ return $this->encode(array(
+ 'id' => $this->_id,
+ 'result' => null,
+ 'error'=> array(
+ 'code' => $exception->getCode(),
+ 'message'=> $exception->getMessage(),
+ 'data' => null,
+ )
+ ));
+ } else {
+ return $this->encode(array(
+ 'id' => $this->_id,
+ 'error'=> array(
+ 'code' => $exception->getCode(),
+ 'message'=> $exception->getMessage(),
+ 'data' => null,
+ )
+ ));
+ }
+ }
+
+ /**
+ * Sets the correct response headers
+ * @param THttpResponse $response
+ */
+ public function createResponseHeaders($response)
+ {
+ $response->setContentType('application/json');
+ $response->setCharset('UTF-8');
+ }
+
+ /**
+ * Decodes JSON encoded data into PHP data
+ * @param string $data in JSON format
+ * @return array PHP data
+ */
+ public function decode($data)
+ {
+ $s = json_decode($data, true);
+ self::checkJsonError();
+ return $s;
+ }
+
+ /**
+ * Encodes PHP data into JSON data
+ * @param mixed PHP data
+ * @return string JSON encoded PHP data
+ */
+ public function encode($data)
+ {
+ $s = json_encode($data);
+ self::checkJsonError();
+ return $s;
+ }
+
+ private static function checkJsonError()
+ {
+ $errnum = json_last_error();
+ if($errnum != JSON_ERROR_NONE)
+ throw new Exception("JSON error: $msg", $err);
+ }
+
+ /**
+ * Calls the callback handler for the given method
+ * Overrides parent implementation to correctly handle error codes
+ * @param string $methodName of the RPC
+ * @param array $parameters for the callback handler as provided by the client
+ * @return mixed whatever the callback handler returns
+ */
+ public function callApiMethod($methodName, $parameters)
+ {
+ if(!isset($this->rpcMethods[$methodName]))
+ throw new TRpcException('Method "'.$methodName.'" not found', '-32601');
+
+ return call_user_func_array($this->rpcMethods[$methodName]['method'], $parameters);
+ }
+} \ No newline at end of file
diff --git a/framework/Web/Services/TJsonService.php b/framework/Web/Services/TJsonService.php
index e3b9b1cb..08d0ec3d 100644
--- a/framework/Web/Services/TJsonService.php
+++ b/framework/Web/Services/TJsonService.php
@@ -158,52 +158,4 @@ class TJsonService extends TService
$response->write(TJavaScript::jsonEncode($content));
}
}
-}
-
-/**
- * TJsonResponse Class
- *
- * TJsonResponse is the base class for all JSON response provider classes.
- *
- * Derived classes must implement {@link getJsonContent()} to return
- * an object or literals to be converted to JSON format. The response
- * will be empty if the returned content is null.
- *
- * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
- * @package System.Web.Services
- * @since 3.1
- */
-abstract class TJsonResponse extends TApplicationComponent
-{
- private $_id='';
-
- /**
- * Initializes the feed.
- * @param TXmlElement configurations specified in {@link TJsonService}.
- */
- public function init($config)
- {
- }
-
- /**
- * @return string ID of this response
- */
- public function getID()
- {
- return $this->_id;
- }
-
- /**
- * @param string ID of this response
- */
- public function setID($value)
- {
- $this->_id=$value;
- }
-
- /**
- * @return object json response content, null to suppress output.
- */
- abstract public function getJsonContent();
-}
-
+} \ No newline at end of file
diff --git a/framework/Web/Services/TPageConfiguration.php b/framework/Web/Services/TPageConfiguration.php
new file mode 100644
index 00000000..7f27cdc6
--- /dev/null
+++ b/framework/Web/Services/TPageConfiguration.php
@@ -0,0 +1,362 @@
+<?php
+/**
+ * TPageService class file.
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright &copy; 2005-2014 PradoSoft
+ * @license http://www.pradosoft.com/license/
+ * @package System.Web.Services
+ */
+
+
+/**
+ * TPageConfiguration class
+ *
+ * TPageConfiguration represents the configuration for a page.
+ * The page is specified by a dot-connected path.
+ * Configurations along this path are merged together to be provided for the page.
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @package System.Web.Services
+ * @since 3.0
+ */
+class TPageConfiguration extends TComponent
+{
+ /**
+ * @var array list of application configurations
+ */
+ private $_appConfigs=array();
+ /**
+ * @var array list of page initial property values
+ */
+ private $_properties=array();
+ /**
+ * @var TAuthorizationRuleCollection list of authorization rules
+ */
+ private $_rules=array();
+ /**
+ * @var array list of included configurations
+ */
+ private $_includes=array();
+ /**
+ * @var string the currently request page in the format of Path.To.PageName
+ */
+ private $_pagePath='';
+
+ /**
+ * Constructor.
+ * @param string the currently request page in the format of Path.To.PageName
+ */
+ public function __construct($pagePath)
+ {
+ $this->_pagePath=$pagePath;
+ }
+
+ /**
+ * @return array list of external configuration files. Each element is like $filePath=>$condition
+ */
+ public function getExternalConfigurations()
+ {
+ return $this->_includes;
+ }
+
+ /**
+ * Returns list of page initial property values.
+ * Each array element represents a single property with the key
+ * being the property name and the value the initial property value.
+ * @return array list of page initial property values
+ */
+ public function getProperties()
+ {
+ return $this->_properties;
+ }
+
+ /**
+ * Returns list of authorization rules.
+ * The authorization rules are aggregated (bottom-up) from configuration files
+ * along the path to the specified page.
+ * @return TAuthorizationRuleCollection collection of authorization rules
+ */
+ public function getRules()
+ {
+ return $this->_rules;
+ }
+
+ /**
+ * @return array list of application configurations specified along page path
+ */
+ public function getApplicationConfigurations()
+ {
+ return $this->_appConfigs;
+ }
+
+ /**
+ * Loads configuration for a page specified in a path format.
+ * @param string root path for pages
+ */
+ public function loadFromFiles($basePath)
+ {
+ $paths=explode('.',$this->_pagePath);
+ $page=array_pop($paths);
+ $path=$basePath;
+ $configPagePath='';
+ $fileName = Prado::getApplication()->getConfigurationType()==TApplication::CONFIG_TYPE_PHP
+ ? TPageService::CONFIG_FILE_PHP
+ : TPageService::CONFIG_FILE_XML;
+ foreach($paths as $p)
+ {
+ $this->loadFromFile($path.DIRECTORY_SEPARATOR.$fileName,$configPagePath);
+ $path.=DIRECTORY_SEPARATOR.$p;
+ if($configPagePath==='')
+ $configPagePath=$p;
+ else
+ $configPagePath.='.'.$p;
+ }
+ $this->loadFromFile($path.DIRECTORY_SEPARATOR.$fileName,$configPagePath);
+ $this->_rules=new TAuthorizationRuleCollection($this->_rules);
+ }
+
+ /**
+ * Loads a specific config file.
+ * @param string config file name
+ * @param string the page path that the config file is associated with. The page path doesn't include the page name.
+ */
+ public function loadFromFile($fname,$configPagePath)
+ {
+ Prado::trace("Loading page configuration file $fname",'System.Web.Services.TPageService');
+ if(empty($fname) || !is_file($fname))
+ return;
+
+ if(Prado::getApplication()->getConfigurationType()==TApplication::CONFIG_TYPE_PHP)
+ {
+ $fcontent = include $fname;
+ $this->loadFromPhp($fcontent,dirname($fname),$configPagePath);
+ }
+ else
+ {
+ $dom=new TXmlDocument;
+ if($dom->loadFromFile($fname))
+ $this->loadFromXml($dom,dirname($fname),$configPagePath);
+ else
+ throw new TConfigurationException('pageserviceconf_file_invalid',$fname);
+ }
+ }
+
+ public function loadFromPhp($config,$configPath,$configPagePath)
+ {
+ $this->loadApplicationConfigurationFromPhp($config,$configPath);
+ $this->loadPageConfigurationFromPhp($config,$configPath,$configPagePath);
+ }
+
+ /**
+ * Loads a page configuration.
+ * The configuration includes information for both application
+ * and page service.
+ * @param TXmlElement config xml element
+ * @param string the directory containing this configuration
+ * @param string the page path that the config XML is associated with. The page path doesn't include the page name.
+ */
+ public function loadFromXml($dom,$configPath,$configPagePath)
+ {
+ $this->loadApplicationConfigurationFromXml($dom,$configPath);
+ $this->loadPageConfigurationFromXml($dom,$configPath,$configPagePath);
+ }
+
+ public function loadApplicationConfigurationFromPhp($config,$configPath)
+ {
+ $appConfig=new TApplicationConfiguration;
+ $appConfig->loadFromPhp($config,$configPath);
+ $this->_appConfigs[]=$appConfig;
+ }
+
+ /**
+ * Loads the configuration specific for application part
+ * @param TXmlElement config xml element
+ * @param string base path corresponding to this xml element
+ */
+ public function loadApplicationConfigurationFromXml($dom,$configPath)
+ {
+ $appConfig=new TApplicationConfiguration;
+ $appConfig->loadFromXml($dom,$configPath);
+ $this->_appConfigs[]=$appConfig;
+ }
+
+ public function loadPageConfigurationFromPhp($config, $configPath, $configPagePath)
+ {
+ // authorization
+ if(isset($config['authorization']) && is_array($config['authorization']))
+ {
+ $rules = array();
+ foreach($config['authorization'] as $authorization)
+ {
+ $patterns=isset($authorization['pages'])?$authorization['pages']:'';
+ $ruleApplies=false;
+ if(empty($patterns) || trim($patterns)==='*') // null or empty string
+ $ruleApplies=true;
+ else
+ {
+ foreach(explode(',',$patterns) as $pattern)
+ {
+ if(($pattern=trim($pattern))!=='')
+ {
+ // we know $configPagePath and $this->_pagePath
+ if($configPagePath!=='') // prepend the pattern with ConfigPagePath
+ $pattern=$configPagePath.'.'.$pattern;
+ if(strcasecmp($pattern,$this->_pagePath)===0)
+ {
+ $ruleApplies=true;
+ break;
+ }
+ if($pattern[strlen($pattern)-1]==='*') // try wildcard matching
+ {
+ if(strncasecmp($this->_pagePath,$pattern,strlen($pattern)-1)===0)
+ {
+ $ruleApplies=true;
+ break;
+ }
+ }
+ }
+ }
+ }
+ if($ruleApplies)
+ {
+ $action = isset($authorization['action'])?$authorization['action']:'';
+ $users = isset($authorization['users'])?$authorization['users']:'';
+ $roles = isset($authorization['roles'])?$authorization['roles']:'';
+ $verb = isset($authorization['verb'])?$authorization['verb']:'';
+ $ips = isset($authorization['ips'])?$authorization['ips']:'';
+ $rules[]=new TAuthorizationRule($action,$users,$roles,$verb,$ips);
+ }
+ }
+ $this->_rules=array_merge($rules,$this->_rules);
+ }
+ // pages
+ if(isset($config['pages']) && is_array($config['pages']))
+ {
+ if(isset($config['pages']['properties']))
+ {
+ $this->_properties = array_merge($this->_properties, $config['pages']['properties']);
+ unset($config['pages']['properties']);
+ }
+ foreach($config['pages'] as $id => $page)
+ {
+ $properties = array();
+ if(isset($page['properties']))
+ {
+ $properties=$page['properties'];
+ unset($page['properties']);
+ }
+ $matching=false;
+ $id=($configPagePath==='')?$id:$configPagePath.'.'.$id;
+ if(strcasecmp($id,$this->_pagePath)===0)
+ $matching=true;
+ else if($id[strlen($id)-1]==='*') // try wildcard matching
+ $matching=strncasecmp($this->_pagePath,$id,strlen($id)-1)===0;
+ if($matching)
+ $this->_properties=array_merge($this->_properties,$properties);
+ }
+ }
+
+ // external configurations
+ if(isset($config['includes']) && is_array($config['includes']))
+ {
+ foreach($config['includes'] as $include)
+ {
+ $when = isset($include['when'])?true:false;
+ if(!isset($include['file']))
+ throw new TConfigurationException('pageserviceconf_includefile_required');
+ $filePath = $include['file'];
+ if(isset($this->_includes[$filePath]))
+ $this->_includes[$filePath]=array($configPagePath,'('.$this->_includes[$filePath][1].') || ('.$when.')');
+ else
+ $this->_includes[$filePath]=array($configPagePath,$when);
+ }
+ }
+ }
+
+ /**
+ * Loads the configuration specific for page service.
+ * @param TXmlElement config xml element
+ * @param string base path corresponding to this xml element
+ * @param string the page path that the config XML is associated with. The page path doesn't include the page name.
+ */
+ public function loadPageConfigurationFromXml($dom,$configPath,$configPagePath)
+ {
+ // authorization
+ if(($authorizationNode=$dom->getElementByTagName('authorization'))!==null)
+ {
+ $rules=array();
+ foreach($authorizationNode->getElements() as $node)
+ {
+ $patterns=$node->getAttribute('pages');
+ $ruleApplies=false;
+ if(empty($patterns) || trim($patterns)==='*') // null or empty string
+ $ruleApplies=true;
+ else
+ {
+ foreach(explode(',',$patterns) as $pattern)
+ {
+ if(($pattern=trim($pattern))!=='')
+ {
+ // we know $configPagePath and $this->_pagePath
+ if($configPagePath!=='') // prepend the pattern with ConfigPagePath
+ $pattern=$configPagePath.'.'.$pattern;
+ if(strcasecmp($pattern,$this->_pagePath)===0)
+ {
+ $ruleApplies=true;
+ break;
+ }
+ if($pattern[strlen($pattern)-1]==='*') // try wildcard matching
+ {
+ if(strncasecmp($this->_pagePath,$pattern,strlen($pattern)-1)===0)
+ {
+ $ruleApplies=true;
+ break;
+ }
+ }
+ }
+ }
+ }
+ if($ruleApplies)
+ $rules[]=new TAuthorizationRule($node->getTagName(),$node->getAttribute('users'),$node->getAttribute('roles'),$node->getAttribute('verb'),$node->getAttribute('ips'));
+ }
+ $this->_rules=array_merge($rules,$this->_rules);
+ }
+
+ // pages
+ if(($pagesNode=$dom->getElementByTagName('pages'))!==null)
+ {
+ $this->_properties=array_merge($this->_properties,$pagesNode->getAttributes()->toArray());
+ // at the page folder
+ foreach($pagesNode->getElementsByTagName('page') as $node)
+ {
+ $properties=$node->getAttributes();
+ $id=$properties->remove('id');
+ if(empty($id))
+ throw new TConfigurationException('pageserviceconf_page_invalid',$configPath);
+ $matching=false;
+ $id=($configPagePath==='')?$id:$configPagePath.'.'.$id;
+ if(strcasecmp($id,$this->_pagePath)===0)
+ $matching=true;
+ else if($id[strlen($id)-1]==='*') // try wildcard matching
+ $matching=strncasecmp($this->_pagePath,$id,strlen($id)-1)===0;
+ if($matching)
+ $this->_properties=array_merge($this->_properties,$properties->toArray());
+ }
+ }
+
+ // external configurations
+ foreach($dom->getElementsByTagName('include') as $node)
+ {
+ if(($when=$node->getAttribute('when'))===null)
+ $when=true;
+ if(($filePath=$node->getAttribute('file'))===null)
+ throw new TConfigurationException('pageserviceconf_includefile_required');
+ if(isset($this->_includes[$filePath]))
+ $this->_includes[$filePath]=array($configPagePath,'('.$this->_includes[$filePath][1].') || ('.$when.')');
+ else
+ $this->_includes[$filePath]=array($configPagePath,$when);
+ }
+ }
+} \ No newline at end of file
diff --git a/framework/Web/Services/TPageService.php b/framework/Web/Services/TPageService.php
index f0dd8c1a..ac64afcf 100644
--- a/framework/Web/Services/TPageService.php
+++ b/framework/Web/Services/TPageService.php
@@ -534,357 +534,4 @@ class TPageService extends TService
{
return $this->getRequest()->constructUrl($this->getID(),$pagePath,$getParams,$encodeAmpersand,$encodeGetItems);
}
-}
-
-
-/**
- * TPageConfiguration class
- *
- * TPageConfiguration represents the configuration for a page.
- * The page is specified by a dot-connected path.
- * Configurations along this path are merged together to be provided for the page.
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @package System.Web.Services
- * @since 3.0
- */
-class TPageConfiguration extends TComponent
-{
- /**
- * @var array list of application configurations
- */
- private $_appConfigs=array();
- /**
- * @var array list of page initial property values
- */
- private $_properties=array();
- /**
- * @var TAuthorizationRuleCollection list of authorization rules
- */
- private $_rules=array();
- /**
- * @var array list of included configurations
- */
- private $_includes=array();
- /**
- * @var string the currently request page in the format of Path.To.PageName
- */
- private $_pagePath='';
-
- /**
- * Constructor.
- * @param string the currently request page in the format of Path.To.PageName
- */
- public function __construct($pagePath)
- {
- $this->_pagePath=$pagePath;
- }
-
- /**
- * @return array list of external configuration files. Each element is like $filePath=>$condition
- */
- public function getExternalConfigurations()
- {
- return $this->_includes;
- }
-
- /**
- * Returns list of page initial property values.
- * Each array element represents a single property with the key
- * being the property name and the value the initial property value.
- * @return array list of page initial property values
- */
- public function getProperties()
- {
- return $this->_properties;
- }
-
- /**
- * Returns list of authorization rules.
- * The authorization rules are aggregated (bottom-up) from configuration files
- * along the path to the specified page.
- * @return TAuthorizationRuleCollection collection of authorization rules
- */
- public function getRules()
- {
- return $this->_rules;
- }
-
- /**
- * @return array list of application configurations specified along page path
- */
- public function getApplicationConfigurations()
- {
- return $this->_appConfigs;
- }
-
- /**
- * Loads configuration for a page specified in a path format.
- * @param string root path for pages
- */
- public function loadFromFiles($basePath)
- {
- $paths=explode('.',$this->_pagePath);
- $page=array_pop($paths);
- $path=$basePath;
- $configPagePath='';
- $fileName = Prado::getApplication()->getConfigurationType()==TApplication::CONFIG_TYPE_PHP
- ? TPageService::CONFIG_FILE_PHP
- : TPageService::CONFIG_FILE_XML;
- foreach($paths as $p)
- {
- $this->loadFromFile($path.DIRECTORY_SEPARATOR.$fileName,$configPagePath);
- $path.=DIRECTORY_SEPARATOR.$p;
- if($configPagePath==='')
- $configPagePath=$p;
- else
- $configPagePath.='.'.$p;
- }
- $this->loadFromFile($path.DIRECTORY_SEPARATOR.$fileName,$configPagePath);
- $this->_rules=new TAuthorizationRuleCollection($this->_rules);
- }
-
- /**
- * Loads a specific config file.
- * @param string config file name
- * @param string the page path that the config file is associated with. The page path doesn't include the page name.
- */
- public function loadFromFile($fname,$configPagePath)
- {
- Prado::trace("Loading page configuration file $fname",'System.Web.Services.TPageService');
- if(empty($fname) || !is_file($fname))
- return;
-
- if(Prado::getApplication()->getConfigurationType()==TApplication::CONFIG_TYPE_PHP)
- {
- $fcontent = include $fname;
- $this->loadFromPhp($fcontent,dirname($fname),$configPagePath);
- }
- else
- {
- $dom=new TXmlDocument;
- if($dom->loadFromFile($fname))
- $this->loadFromXml($dom,dirname($fname),$configPagePath);
- else
- throw new TConfigurationException('pageserviceconf_file_invalid',$fname);
- }
- }
-
- public function loadFromPhp($config,$configPath,$configPagePath)
- {
- $this->loadApplicationConfigurationFromPhp($config,$configPath);
- $this->loadPageConfigurationFromPhp($config,$configPath,$configPagePath);
- }
-
- /**
- * Loads a page configuration.
- * The configuration includes information for both application
- * and page service.
- * @param TXmlElement config xml element
- * @param string the directory containing this configuration
- * @param string the page path that the config XML is associated with. The page path doesn't include the page name.
- */
- public function loadFromXml($dom,$configPath,$configPagePath)
- {
- $this->loadApplicationConfigurationFromXml($dom,$configPath);
- $this->loadPageConfigurationFromXml($dom,$configPath,$configPagePath);
- }
-
- public function loadApplicationConfigurationFromPhp($config,$configPath)
- {
- $appConfig=new TApplicationConfiguration;
- $appConfig->loadFromPhp($config,$configPath);
- $this->_appConfigs[]=$appConfig;
- }
-
- /**
- * Loads the configuration specific for application part
- * @param TXmlElement config xml element
- * @param string base path corresponding to this xml element
- */
- public function loadApplicationConfigurationFromXml($dom,$configPath)
- {
- $appConfig=new TApplicationConfiguration;
- $appConfig->loadFromXml($dom,$configPath);
- $this->_appConfigs[]=$appConfig;
- }
-
- public function loadPageConfigurationFromPhp($config, $configPath, $configPagePath)
- {
- // authorization
- if(isset($config['authorization']) && is_array($config['authorization']))
- {
- $rules = array();
- foreach($config['authorization'] as $authorization)
- {
- $patterns=isset($authorization['pages'])?$authorization['pages']:'';
- $ruleApplies=false;
- if(empty($patterns) || trim($patterns)==='*') // null or empty string
- $ruleApplies=true;
- else
- {
- foreach(explode(',',$patterns) as $pattern)
- {
- if(($pattern=trim($pattern))!=='')
- {
- // we know $configPagePath and $this->_pagePath
- if($configPagePath!=='') // prepend the pattern with ConfigPagePath
- $pattern=$configPagePath.'.'.$pattern;
- if(strcasecmp($pattern,$this->_pagePath)===0)
- {
- $ruleApplies=true;
- break;
- }
- if($pattern[strlen($pattern)-1]==='*') // try wildcard matching
- {
- if(strncasecmp($this->_pagePath,$pattern,strlen($pattern)-1)===0)
- {
- $ruleApplies=true;
- break;
- }
- }
- }
- }
- }
- if($ruleApplies)
- {
- $action = isset($authorization['action'])?$authorization['action']:'';
- $users = isset($authorization['users'])?$authorization['users']:'';
- $roles = isset($authorization['roles'])?$authorization['roles']:'';
- $verb = isset($authorization['verb'])?$authorization['verb']:'';
- $ips = isset($authorization['ips'])?$authorization['ips']:'';
- $rules[]=new TAuthorizationRule($action,$users,$roles,$verb,$ips);
- }
- }
- $this->_rules=array_merge($rules,$this->_rules);
- }
- // pages
- if(isset($config['pages']) && is_array($config['pages']))
- {
- if(isset($config['pages']['properties']))
- {
- $this->_properties = array_merge($this->_properties, $config['pages']['properties']);
- unset($config['pages']['properties']);
- }
- foreach($config['pages'] as $id => $page)
- {
- $properties = array();
- if(isset($page['properties']))
- {
- $properties=$page['properties'];
- unset($page['properties']);
- }
- $matching=false;
- $id=($configPagePath==='')?$id:$configPagePath.'.'.$id;
- if(strcasecmp($id,$this->_pagePath)===0)
- $matching=true;
- else if($id[strlen($id)-1]==='*') // try wildcard matching
- $matching=strncasecmp($this->_pagePath,$id,strlen($id)-1)===0;
- if($matching)
- $this->_properties=array_merge($this->_properties,$properties);
- }
- }
-
- // external configurations
- if(isset($config['includes']) && is_array($config['includes']))
- {
- foreach($config['includes'] as $include)
- {
- $when = isset($include['when'])?true:false;
- if(!isset($include['file']))
- throw new TConfigurationException('pageserviceconf_includefile_required');
- $filePath = $include['file'];
- if(isset($this->_includes[$filePath]))
- $this->_includes[$filePath]=array($configPagePath,'('.$this->_includes[$filePath][1].') || ('.$when.')');
- else
- $this->_includes[$filePath]=array($configPagePath,$when);
- }
- }
- }
-
- /**
- * Loads the configuration specific for page service.
- * @param TXmlElement config xml element
- * @param string base path corresponding to this xml element
- * @param string the page path that the config XML is associated with. The page path doesn't include the page name.
- */
- public function loadPageConfigurationFromXml($dom,$configPath,$configPagePath)
- {
- // authorization
- if(($authorizationNode=$dom->getElementByTagName('authorization'))!==null)
- {
- $rules=array();
- foreach($authorizationNode->getElements() as $node)
- {
- $patterns=$node->getAttribute('pages');
- $ruleApplies=false;
- if(empty($patterns) || trim($patterns)==='*') // null or empty string
- $ruleApplies=true;
- else
- {
- foreach(explode(',',$patterns) as $pattern)
- {
- if(($pattern=trim($pattern))!=='')
- {
- // we know $configPagePath and $this->_pagePath
- if($configPagePath!=='') // prepend the pattern with ConfigPagePath
- $pattern=$configPagePath.'.'.$pattern;
- if(strcasecmp($pattern,$this->_pagePath)===0)
- {
- $ruleApplies=true;
- break;
- }
- if($pattern[strlen($pattern)-1]==='*') // try wildcard matching
- {
- if(strncasecmp($this->_pagePath,$pattern,strlen($pattern)-1)===0)
- {
- $ruleApplies=true;
- break;
- }
- }
- }
- }
- }
- if($ruleApplies)
- $rules[]=new TAuthorizationRule($node->getTagName(),$node->getAttribute('users'),$node->getAttribute('roles'),$node->getAttribute('verb'),$node->getAttribute('ips'));
- }
- $this->_rules=array_merge($rules,$this->_rules);
- }
-
- // pages
- if(($pagesNode=$dom->getElementByTagName('pages'))!==null)
- {
- $this->_properties=array_merge($this->_properties,$pagesNode->getAttributes()->toArray());
- // at the page folder
- foreach($pagesNode->getElementsByTagName('page') as $node)
- {
- $properties=$node->getAttributes();
- $id=$properties->remove('id');
- if(empty($id))
- throw new TConfigurationException('pageserviceconf_page_invalid',$configPath);
- $matching=false;
- $id=($configPagePath==='')?$id:$configPagePath.'.'.$id;
- if(strcasecmp($id,$this->_pagePath)===0)
- $matching=true;
- else if($id[strlen($id)-1]==='*') // try wildcard matching
- $matching=strncasecmp($this->_pagePath,$id,strlen($id)-1)===0;
- if($matching)
- $this->_properties=array_merge($this->_properties,$properties->toArray());
- }
- }
-
- // external configurations
- foreach($dom->getElementsByTagName('include') as $node)
- {
- if(($when=$node->getAttribute('when'))===null)
- $when=true;
- if(($filePath=$node->getAttribute('file'))===null)
- throw new TConfigurationException('pageserviceconf_includefile_required');
- if(isset($this->_includes[$filePath]))
- $this->_includes[$filePath]=array($configPagePath,'('.$this->_includes[$filePath][1].') || ('.$when.')');
- else
- $this->_includes[$filePath]=array($configPagePath,$when);
- }
- }
-}
-
+} \ No newline at end of file
diff --git a/framework/Web/Services/TRpcApiProvider.php b/framework/Web/Services/TRpcApiProvider.php
new file mode 100644
index 00000000..6ea1abfc
--- /dev/null
+++ b/framework/Web/Services/TRpcApiProvider.php
@@ -0,0 +1,86 @@
+<?php
+/**
+ * @author Robin J. Rogge <rrogge@bigpoint.net>
+ * @link http://www.pradosoft.com/
+ * @copyright 2010 Bigpoint GmbH
+ * @license http://www.pradosoft.com/license/
+ * @version $Id$
+ * @since 3.2
+ * @package System.Web.Services
+ */
+
+/**
+ * TRpcApiProvider class
+ *
+ * TRpcApiProvider is an abstract class the can be subclasses in order to implement an
+ * api for a {@link TRpcService}. A subclass of TRpcApiProvider must implement the
+ * {@link registerMethods} method in order to declare the available methods, their
+ * names and the associated callback.
+ *
+ * <code>
+ * public function registerMethods()
+ * {
+ * return array(
+ * 'apiMethodName1' => array('method' => array($this, 'objectMethodName1')),
+ * 'apiMethodName2' => array('method' => array('ClassName', 'staticMethodName')),
+ * );
+ * }
+ * </code>
+ *
+ * In this example, two api method have been defined. The first refers to an object
+ * method that must be implemented in the same class, the second to a static method
+ * implemented in a 'ClassName' class.
+ * In both cases, the method implementation will receive the request parameters as its
+ * method parameters. Since the number of received parameters depends on
+ * external-supplied data, it's adviced to use php's func_get_args() funtion to
+ * validate them.
+ *
+ * Providers must be registered in the service configuration in order to be available,
+ * as explained in {@link TRpcService}'s documentation.
+ *
+ * @author Robin J. Rogge <rrogge@bigpoint.net>
+ * @version $Id$
+ * @package System.Web.Services
+ * @since 3.2
+ */
+abstract class TRpcApiProvider extends TModule
+{
+ /**
+ * @var TRpcServer instance
+ */
+ protected $rpcServer;
+
+ /**
+ * Must return an array of the available methods
+ * @abstract
+ */
+ abstract public function registerMethods();
+
+ /**
+ * Constructor: informs the rpc server of the registered methods
+ */
+ public function __construct(TRpcServer $rpcServer)
+ {
+ $this->rpcServer = $rpcServer;
+
+ foreach($this->registerMethods() as $_methodName => $_methodDetails)
+ $this->rpcServer->addRpcMethod($_methodName, $_methodDetails);
+ }
+
+ /**
+ * Processes the request using the server
+ * @return processed request
+ */
+ public function processRequest()
+ {
+ return $this->rpcServer->processRequest();
+ }
+
+ /**
+ * @return rpc server instance
+ */
+ public function getRpcServer()
+ {
+ return $this->rpcServer;
+ }
+} \ No newline at end of file
diff --git a/framework/Web/Services/TRpcException.php b/framework/Web/Services/TRpcException.php
new file mode 100644
index 00000000..7c0cb65f
--- /dev/null
+++ b/framework/Web/Services/TRpcException.php
@@ -0,0 +1,31 @@
+<?php
+/**
+ * @author Robin J. Rogge <rrogge@bigpoint.net>
+ * @link http://www.pradosoft.com/
+ * @copyright 2010 Bigpoint GmbH
+ * @license http://www.pradosoft.com/license/
+ * @version $Id$
+ * @since 3.2
+ * @package System.Web.Services
+ */
+
+/**
+ * TRpcException class
+ *
+ * A TRpcException represents a RPC fault i.e. an error that is caused by the input data
+ * sent from the client.
+ *
+ * @author Robin J. Rogge <rrogge@bigpoint.net>
+ * @version $Id$
+ * @package System.Web.Services
+ * @since 3.2
+ */
+class TRpcException extends TException
+{
+ public function __construct($message, $errorCode = -1)
+ {
+ $this->setErrorCode($errorCode);
+
+ parent::__construct($message);
+ }
+} \ No newline at end of file
diff --git a/framework/Web/Services/TRpcProtocol.php b/framework/Web/Services/TRpcProtocol.php
new file mode 100644
index 00000000..ace13638
--- /dev/null
+++ b/framework/Web/Services/TRpcProtocol.php
@@ -0,0 +1,98 @@
+<?php
+/**
+ * @author Robin J. Rogge <rrogge@bigpoint.net>
+ * @link http://www.pradosoft.com/
+ * @copyright 2010 Bigpoint GmbH
+ * @license http://www.pradosoft.com/license/
+ * @version $Id$
+ * @since 3.2
+ * @package System.Web.Services
+ */
+
+/**
+ * TRpcProtocol class
+ *
+ * TRpcProtocol is the base class used to implement a protocol in a {@link TRpcService}.
+ * Prado already implements two protocols: {@link TXmlRpcProtocol} for Xml-Rpc request
+ * and {@link TJsonRpcProtocol} for JSON-Rpc requests.
+ *
+ * @author Robin J. Rogge <rrogge@bigpoint.net>
+ * @version $Id$
+ * @package System.Web.Services
+ * @since 3.2
+ **/
+abstract class TRpcProtocol
+{
+ /**
+ * @var array containing the mapping from RPC method names to the actual handlers
+ */
+ protected $rpcMethods = array();
+
+ // abstracts
+
+ /**
+ * @param string request payload
+ * Processed the request ans returns the response, if any
+ * @return processed response
+ * @abstract
+ */
+ abstract public function callMethod($requestPayload);
+ /**
+ * @param TRpcException the exception with error details
+ * Creates a proper response for an error condition
+ * @return a response representing the error
+ * @abstract
+ */
+ abstract public function createErrorResponse(TRpcException $exception);
+ /**
+ * @param response
+ * Sets the needed headers for the response (eg: content-type, charset)
+ * @abstract
+ */
+ abstract public function createResponseHeaders($response);
+ /**
+ * Encodes the response
+ * @param mixed reponse data
+ * @return string encoded response
+ * @abstract
+ */
+ abstract public function encode($data);
+ /**
+ * Decodes the request payload
+ * @param string request payload
+ * @return mixed decoded request
+ * @abstract
+ */
+ abstract public function decode($data);
+
+ // methods
+
+ /**
+ * Registers a new RPC method and handler details
+ * @param string $methodName
+ * @param array $handlerDetails containing the callback handler
+ */
+ public function addMethod($methodName, $handlerDetails)
+ {
+ $this->rpcMethods[$methodName] = $handlerDetails;
+ }
+
+ /**
+ * Calls the callback handler for the given method
+ * @param string $methodName of the RPC
+ * @param array $parameters for the callback handler as provided by the client
+ * @return mixed whatever the callback handler returns
+ */
+ public function callApiMethod($methodName, $parameters)
+ {
+ if(!isset($this->rpcMethods[$methodName]))
+ throw new TRpcException('Method "'.$methodName.'" not found');
+
+ if($parameters === null)
+ $parameters = array();
+
+ if(!is_array($parameters))
+ $parameters = array($parameters);
+ return call_user_func_array($this->rpcMethods[$methodName]['method'], $parameters);
+ }
+} \ No newline at end of file
diff --git a/framework/Web/Services/TRpcServer.php b/framework/Web/Services/TRpcServer.php
new file mode 100644
index 00000000..ab8dd17d
--- /dev/null
+++ b/framework/Web/Services/TRpcServer.php
@@ -0,0 +1,78 @@
+<?php
+/**
+ * @author Robin J. Rogge <rrogge@bigpoint.net>
+ * @link http://www.pradosoft.com/
+ * @copyright 2010 Bigpoint GmbH
+ * @license http://www.pradosoft.com/license/
+ * @version $Id$
+ * @since 3.2
+ * @package System.Web.Services
+ */
+
+/**
+ * TRpcServer class
+ *
+ * TRpcServer is a class
+ *
+ * TRpcServer is the base class used to creare a server to be used in conjunction with
+ * {@link TRpcService}.
+ * The role of TRpcServer is to be an intermediate, moving data between the service and
+ * the provider. This base class should suit the most common needs, but can be sublassed for
+ * logging and debugging purposes, or to filter and modify the request/response on the fly.
+ *
+ * @author Robin J. Rogge <rrogge@bigpoint.net>
+ * @version $Id$
+ * @package System.Web.Services
+ * @since 3.2
+ **/
+class TRpcServer extends TModule
+{
+ /**
+ * @var TRpcProtocol instance
+ */
+ protected $handler;
+
+ /**
+ * Constructor
+ * @param TRpcProtocol $protocolHandler instance
+ */
+ public function __construct(TRpcProtocol $protocolHandler)
+ {
+ $this->handler = $protocolHandler;
+ }
+
+ /**
+ * Registers the method in the protocol handler
+ * @param string $methodName
+ * @param array $methodDetails
+ */
+ public function addRpcMethod($methodName, $methodDetails)
+ {
+ $this->handler->addMethod($methodName, $methodDetails);
+ }
+
+ /**
+ * Retrieves the request payload
+ * @return string request payload
+ */
+ public function getPayload()
+ {
+ return file_get_contents('php://input');
+ }
+
+ /**
+ * Passes the request payload to the protocol handler and returns the result
+ * @return string rpc response
+ */
+ public function processRequest()
+ {
+ try
+ {
+ return $this->handler->callMethod($this->getPayload());
+ }
+ catch(TRpcException $e)
+ {
+ return $this->handler->createErrorResponse($e);
+ }
+ }
+} \ No newline at end of file
diff --git a/framework/Web/Services/TRpcService.php b/framework/Web/Services/TRpcService.php
index a4ed3d7c..26e7471d 100644
--- a/framework/Web/Services/TRpcService.php
+++ b/framework/Web/Services/TRpcService.php
@@ -1,5 +1,4 @@
<?php
-
/**
* @author Robin J. Rogge <rrogge@bigpoint.net>
* @link http://www.pradosoft.com/
@@ -10,6 +9,7 @@
* @package System.Web.Services
*/
+
/**
* TRpcService class
*
@@ -175,548 +175,4 @@ class TRpcService extends TService
$_response->write($_result);
}
}
-}
-
-/**
- * TRpcServer class
- *
- * TRpcServer is a class
- *
- * TRpcServer is the base class used to creare a server to be used in conjunction with
- * {@link TRpcService}.
- * The role of TRpcServer is to be an intermediate, moving data between the service and
- * the provider. This base class should suit the most common needs, but can be sublassed for
- * logging and debugging purposes, or to filter and modify the request/response on the fly.
- *
- * @author Robin J. Rogge <rrogge@bigpoint.net>
- * @version $Id$
- * @package System.Web.Services
- * @since 3.2
- **/
-class TRpcServer extends TModule
-{
- /**
- * @var TRpcProtocol instance
- */
- protected $handler;
-
- /**
- * Constructor
- * @param TRpcProtocol $protocolHandler instance
- */
- public function __construct(TRpcProtocol $protocolHandler)
- {
- $this->handler = $protocolHandler;
- }
-
- /**
- * Registers the method in the protocol handler
- * @param string $methodName
- * @param array $methodDetails
- */
- public function addRpcMethod($methodName, $methodDetails)
- {
- $this->handler->addMethod($methodName, $methodDetails);
- }
-
- /**
- * Retrieves the request payload
- * @return string request payload
- */
- public function getPayload()
- {
- return file_get_contents('php://input');
- }
-
- /**
- * Passes the request payload to the protocol handler and returns the result
- * @return string rpc response
- */
- public function processRequest()
- {
- try
- {
- return $this->handler->callMethod($this->getPayload());
- }
- catch(TRpcException $e)
- {
- return $this->handler->createErrorResponse($e);
- }
- }
-}
-
-/**
- * TRpcException class
- *
- * A TRpcException represents a RPC fault i.e. an error that is caused by the input data
- * sent from the client.
- *
- * @author Robin J. Rogge <rrogge@bigpoint.net>
- * @version $Id$
- * @package System.Web.Services
- * @since 3.2
- */
-class TRpcException extends TException
-{
- public function __construct($message, $errorCode = -1)
- {
- $this->setErrorCode($errorCode);
-
- parent::__construct($message);
- }
-}
-
-/**
- * TRpcApiProvider class
- *
- * TRpcApiProvider is an abstract class the can be subclasses in order to implement an
- * api for a {@link TRpcService}. A subclass of TRpcApiProvider must implement the
- * {@link registerMethods} method in order to declare the available methods, their
- * names and the associated callback.
- *
- * <code>
- * public function registerMethods()
- * {
- * return array(
- * 'apiMethodName1' => array('method' => array($this, 'objectMethodName1')),
- * 'apiMethodName2' => array('method' => array('ClassName', 'staticMethodName')),
- * );
- * }
- * </code>
- *
- * In this example, two api method have been defined. The first refers to an object
- * method that must be implemented in the same class, the second to a static method
- * implemented in a 'ClassName' class.
- * In both cases, the method implementation will receive the request parameters as its
- * method parameters. Since the number of received parameters depends on
- * external-supplied data, it's adviced to use php's func_get_args() funtion to
- * validate them.
- *
- * Providers must be registered in the service configuration in order to be available,
- * as explained in {@link TRpcService}'s documentation.
- *
- * @author Robin J. Rogge <rrogge@bigpoint.net>
- * @version $Id$
- * @package System.Web.Services
- * @since 3.2
- */
-abstract class TRpcApiProvider extends TModule
-{
- /**
- * @var TRpcServer instance
- */
- protected $rpcServer;
-
- /**
- * Must return an array of the available methods
- * @abstract
- */
- abstract public function registerMethods();
-
- /**
- * Constructor: informs the rpc server of the registered methods
- */
- public function __construct(TRpcServer $rpcServer)
- {
- $this->rpcServer = $rpcServer;
-
- foreach($this->registerMethods() as $_methodName => $_methodDetails)
- $this->rpcServer->addRpcMethod($_methodName, $_methodDetails);
- }
-
- /**
- * Processes the request using the server
- * @return processed request
- */
- public function processRequest()
- {
- return $this->rpcServer->processRequest();
- }
-
- /**
- * @return rpc server instance
- */
- public function getRpcServer()
- {
- return $this->rpcServer;
- }
-}
-
-/**
- * TRpcProtocol class
- *
- * TRpcProtocol is the base class used to implement a protocol in a {@link TRpcService}.
- * Prado already implements two protocols: {@link TXmlRpcProtocol} for Xml-Rpc request
- * and {@link TJsonRpcProtocol} for JSON-Rpc requests.
- *
- * @author Robin J. Rogge <rrogge@bigpoint.net>
- * @version $Id$
- * @package System.Web.Services
- * @since 3.2
- **/
-abstract class TRpcProtocol
-{
- /**
- * @var array containing the mapping from RPC method names to the actual handlers
- */
- protected $rpcMethods = array();
-
- // abstracts
-
- /**
- * @param string request payload
- * Processed the request ans returns the response, if any
- * @return processed response
- * @abstract
- */
- abstract public function callMethod($requestPayload);
- /**
- * @param TRpcException the exception with error details
- * Creates a proper response for an error condition
- * @return a response representing the error
- * @abstract
- */
- abstract public function createErrorResponse(TRpcException $exception);
- /**
- * @param response
- * Sets the needed headers for the response (eg: content-type, charset)
- * @abstract
- */
- abstract public function createResponseHeaders($response);
- /**
- * Encodes the response
- * @param mixed reponse data
- * @return string encoded response
- * @abstract
- */
- abstract public function encode($data);
- /**
- * Decodes the request payload
- * @param string request payload
- * @return mixed decoded request
- * @abstract
- */
- abstract public function decode($data);
-
- // methods
-
- /**
- * Registers a new RPC method and handler details
- * @param string $methodName
- * @param array $handlerDetails containing the callback handler
- */
- public function addMethod($methodName, $handlerDetails)
- {
- $this->rpcMethods[$methodName] = $handlerDetails;
- }
-
- /**
- * Calls the callback handler for the given method
- * @param string $methodName of the RPC
- * @param array $parameters for the callback handler as provided by the client
- * @return mixed whatever the callback handler returns
- */
- public function callApiMethod($methodName, $parameters)
- {
- if(!isset($this->rpcMethods[$methodName]))
- throw new TRpcException('Method "'.$methodName.'" not found');
-
- if($parameters === null)
- $parameters = array();
-
- if(!is_array($parameters))
- $parameters = array($parameters);
- return call_user_func_array($this->rpcMethods[$methodName]['method'], $parameters);
- }
-}
-
-/**
- * TJsonRpcProtocol class
- *
- * TJsonRpcProtocol is a class that implements JSON-Rpc protocol in {@link TRpcService}.
- * Both version 1.0 and 2.0 of the specification are implemented, and the server will try
- * to answer using the same version of the protocol used by the requesting client.
- *
- * @author Robin J. Rogge <rrogge@bigpoint.net>
- * @author Fabio Bas <ctrlaltca@gmail.com>
- * @version $Id$
- * @package System.Web.Services
- * @since 3.2
- */
-class TJsonRpcProtocol extends TRpcProtocol
-{
- protected $_id=null;
- protected $_specificationVersion=1.0;
-
- /**
- * Handles the RPC request
- * @param string $requestPayload
- * @return string JSON RPC response
- */
- public function callMethod($requestPayload)
- {
- try
- {
- $_request = $this->decode($requestPayload);
-
- if(isset($_request['jsonrpc']))
- {
- $this->_specificationVersion=$_request['jsonrpc'];
- if($this->_specificationVersion > 2.0)
- throw new TRpcException('Unsupported specification version', '-32600');
- }
-
- if(isset($_request['id']))
- $this->_id=$_request['id'];
-
- if(!isset($_request['method']))
- throw new TRpcException('Missing request method', '-32600');
-
- if(!isset($_request['params']))
- $parameters = array();
- else
- $parameters = $_request['params'];
-
- if(!is_array($parameters))
- $parameters = array($parameters);
-
- // a request without an id is a notification that doesn't need a response
- if($this->_id !== null)
- {
- if($this->_specificationVersion==2.0)
- {
- return $this->encode(array(
- 'jsonrpc' => '2.0',
- 'id' => $this->_id,
- 'result' => $this->callApiMethod($_request['method'], $parameters),
- ));
- } else {
- return $this->encode(array(
- 'id' => $this->_id,
- 'result' => $this->callApiMethod($_request['method'], $_request['params']),
- 'error' => null
- ));
- }
- }
- }
- catch(TRpcException $e)
- {
- return $this->createErrorResponse($e);
- }
- catch(THttpException $e)
- {
- throw $e;
- }
- catch(Exception $e)
- {
- return $this->createErrorResponse(new TRpcException('An internal error occured', '-32603'));
- }
- }
-
- /**
- * Turns the given exception into an JSON RPC fault
- * @param TRpcException $exception
- * @return string JSON RPC fault
- */
- public function createErrorResponse(TRpcException $exception)
- {
- if($this->_specificationVersion==2.0)
- {
- return $this->encode(array(
- 'id' => $this->_id,
- 'result' => null,
- 'error'=> array(
- 'code' => $exception->getCode(),
- 'message'=> $exception->getMessage(),
- 'data' => null,
- )
- ));
- } else {
- return $this->encode(array(
- 'id' => $this->_id,
- 'error'=> array(
- 'code' => $exception->getCode(),
- 'message'=> $exception->getMessage(),
- 'data' => null,
- )
- ));
- }
- }
-
- /**
- * Sets the correct response headers
- * @param THttpResponse $response
- */
- public function createResponseHeaders($response)
- {
- $response->setContentType('application/json');
- $response->setCharset('UTF-8');
- }
-
- /**
- * Decodes JSON encoded data into PHP data
- * @param string $data in JSON format
- * @return array PHP data
- */
- public function decode($data)
- {
- $s = json_decode($data, true);
- self::checkJsonError();
- return $s;
- }
-
- /**
- * Encodes PHP data into JSON data
- * @param mixed PHP data
- * @return string JSON encoded PHP data
- */
- public function encode($data)
- {
- $s = json_encode($data);
- self::checkJsonError();
- return $s;
- }
-
- private static function checkJsonError()
- {
- $errnum = json_last_error();
- if($errnum != JSON_ERROR_NONE)
- throw new Exception("JSON error: $msg", $err);
- }
-
- /**
- * Calls the callback handler for the given method
- * Overrides parent implementation to correctly handle error codes
- * @param string $methodName of the RPC
- * @param array $parameters for the callback handler as provided by the client
- * @return mixed whatever the callback handler returns
- */
- public function callApiMethod($methodName, $parameters)
- {
- if(!isset($this->rpcMethods[$methodName]))
- throw new TRpcException('Method "'.$methodName.'" not found', '-32601');
-
- return call_user_func_array($this->rpcMethods[$methodName]['method'], $parameters);
- }
-}
-
-/**
- * TXmlRpcProtocol class
- *
- * TXmlRpcProtocol is a class that implements XML-Rpc protocol in {@link TRpcService}.
- * It's basically a wrapper to the xmlrpc_server_* family of php methods.
- *
- * @author Robin J. Rogge <rrogge@bigpoint.net>
- * @version $Id$
- * @package System.Web.Services
- * @since 3.2
- */
-class TXmlRpcProtocol extends TRpcProtocol
-{
- /**
- * @var XML RPC server resource
- */
- private $_xmlrpcServer;
-
- // magics
-
- /**
- * Constructor
- */
- public function __construct()
- {
- $this->_xmlrpcServer = xmlrpc_server_create();
- }
-
- /**
- * Destructor
- */
- public function __destruct()
- {
- xmlrpc_server_destroy($this->_xmlrpcServer);
- }
-
- // methods
-
- /**
- * Registers a new RPC method and handler details
- * @param string $methodName
- * @param array $handlerDetails containing the callback handler
- */
- public function addMethod($methodName, $methodDetails)
- {
- parent::addMethod($methodName, $methodDetails);
-
- xmlrpc_server_register_method($this->_xmlrpcServer, $methodName, array($this, 'callApiMethod'));
- }
-
- // methods
-
- /**
- * Handles the RPC request
- * @param string $requestPayload
- * @return string XML RPC response
- */
- public function callMethod($requestPayload)
- {
- try
- {
- return xmlrpc_server_call_method($this->_xmlrpcServer, $requestPayload, null);
- }
- catch(TRpcException $e)
- {
- return $this->createErrorResponse($e);
- }
- catch(THttpException $e)
- {
- throw $e;
- }
- catch(Exception $e)
- {
- return $this->createErrorResponse(new TRpcException('An internal error occured'));
- }
- }
-
- /**
- * Turns the given exception into an XML RPC fault
- * @param TRpcException $exception
- * @return string XML RPC fault
- */
- public function createErrorResponse(TRpcException $exception)
- {
- return $this->encode(array(
- 'faultCode' => $exception->getCode(),
- 'faultString' => $exception->getMessage()
- ));
- }
-
- /**
- * Sets the correct response headers
- * @param THttpResponse $response
- */
- public function createResponseHeaders($response)
- {
- $response->setContentType('text/xml');
- $response->setCharset('UTF-8');
- }
-
- /**
- * Decodes XML encoded data into PHP data
- * @param string $data in XML format
- * @return array PHP data
- */
- public function decode($data)
- {
- return xmlrpc_decode($data);
- }
-
- /**
- * Encodes PHP data into XML data
- * @param mixed PHP data
- * @return string XML encoded PHP data
- */
- public function encode($data)
- {
- return xmlrpc_encode($data);
- }
-}
+} \ No newline at end of file
diff --git a/framework/Web/Services/TSoapServer.php b/framework/Web/Services/TSoapServer.php
new file mode 100644
index 00000000..0441e67d
--- /dev/null
+++ b/framework/Web/Services/TSoapServer.php
@@ -0,0 +1,345 @@
+<?php
+/**
+ * TSoapService and TSoapServer class file
+ *
+ * @author Knut Urdalen <knut.urdalen@gmail.com>
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright &copy; 2005-2014 PradoSoft
+ * @license http://www.pradosoft.com/license/
+ * @package System.Web.Services
+ */
+
+
+/**
+ * TSoapServer class.
+ *
+ * TSoapServer is a wrapper of the PHP SoapServer class.
+ * It associates a SOAP provider class to the SoapServer object.
+ * It also manages the URI for the SOAP service and WSDL.
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @package System.Web.Services
+ * @since 3.1
+ */
+class TSoapServer extends TApplicationComponent
+{
+ const WSDL_CACHE_PREFIX='wsdl.';
+
+ private $_id;
+ private $_provider;
+
+ private $_version='';
+ private $_actor='';
+ private $_encoding='';
+ private $_uri='';
+ private $_classMap;
+ private $_persistent=false;
+ private $_wsdlUri='';
+
+ private $_requestedMethod;
+
+ private $_server;
+
+ /**
+ * @return string the ID of the SOAP server
+ */
+ public function getID()
+ {
+ return $this->_id;
+ }
+
+ /**
+ * @param string the ID of the SOAP server
+ * @throws TInvalidDataValueException if the ID ends with '.wsdl'.
+ */
+ public function setID($id)
+ {
+ if(strrpos($this->_id,'.wsdl')===strlen($this->_id)-5)
+ throw new TInvalidDataValueException('soapserver_id_invalid',$id);
+ $this->_id=$id;
+ }
+
+ /**
+ * Handles the SOAP request.
+ */
+ public function run()
+ {
+ if(($provider=$this->getProvider())!==null)
+ {
+ Prado::using($provider);
+ $providerClass=($pos=strrpos($provider,'.'))!==false?substr($provider,$pos+1):$provider;
+ $this->guessMethodCallRequested($providerClass);
+ $server=$this->createServer();
+ $server->setClass($providerClass, $this);
+ if($this->_persistent)
+ $server->setPersistence(SOAP_PERSISTENCE_SESSION);
+ }
+ else
+ $server=$this->createServer();
+ try
+ {
+ $server->handle();
+ }
+ catch (Exception $e)
+ {
+ if($this->getApplication()->getMode()===TApplicationMode::Debug)
+ $this->fault($e->getMessage(), $e->__toString());
+ else
+ $this->fault($e->getMessage());
+ }
+ }
+
+ /**
+ * Generate a SOAP fault message.
+ * @param string message title
+ * @param mixed message details
+ * @param string message code, defalt is 'SERVER'.
+ * @param string actors
+ * @param string message name
+ */
+ public function fault($title, $details='', $code='SERVER', $actor='', $name='')
+ {
+ Prado::trace('SOAP-Fault '.$code. ' '.$title.' : '.$details, 'System.Web.Services.TSoapService');
+ $this->_server->fault($code, $title, $actor, $details, $name);
+ }
+
+ /**
+ * Guess the SOAP method request from the actual SOAP message
+ *
+ * @param string $class current handler class.
+ */
+ protected function guessMethodCallRequested($class)
+ {
+ $namespace = $class.'wsdl';
+ $message = file_get_contents("php://input");
+ $matches= array();
+ if(preg_match('/xmlns:([^=]+)="urn:'.$namespace.'"/', $message, $matches))
+ {
+ if(preg_match('/<'.$matches[1].':([a-zA-Z_]+[a-zA-Z0-9_]+)/', $message, $method))
+ {
+ $this->_requestedMethod = $method[1];
+ }
+ }
+ }
+
+ /**
+ * Soap method guessed from the SOAP message received.
+ * @return string soap method request, null if not found.
+ */
+ public function getRequestedMethod()
+ {
+ return $this->_requestedMethod;
+ }
+
+ /**
+ * Creates the SoapServer instance.
+ * @return SoapServer
+ */
+ protected function createServer()
+ {
+ if($this->_server===null)
+ {
+ if($this->getApplication()->getMode()===TApplicationMode::Debug)
+ ini_set("soap.wsdl_cache_enabled",0);
+ $this->_server = new SoapServer($this->getWsdlUri(),$this->getOptions());
+ }
+ return $this->_server;
+ }
+
+ /**
+ * @return array options for creating SoapServer instance
+ */
+ protected function getOptions()
+ {
+ $options=array();
+ if($this->_version==='1.1')
+ $options['soap_version']=SOAP_1_1;
+ else if($this->_version==='1.2')
+ $options['soap_version']=SOAP_1_2;
+ if(!empty($this->_actor))
+ $options['actor']=$this->_actor;
+ if(!empty($this->_encoding))
+ $options['encoding']=$this->_encoding;
+ if(!empty($this->_uri))
+ $options['uri']=$this->_uri;
+ if(is_string($this->_classMap))
+ {
+ foreach(preg_split('/\s*,\s*/', $this->_classMap) as $className)
+ $options['classmap'][$className]=$className; //complex type uses the class name in the wsdl
+ }
+ return $options;
+ }
+
+ /**
+ * Returns the WSDL content of the SOAP server.
+ * If {@link getWsdlUri WsdlUri} is set, its content will be returned.
+ * If not, the {@link setProvider Provider} class will be investigated
+ * and the WSDL will be automatically genearted.
+ * @return string the WSDL content of the SOAP server
+ */
+ public function getWsdl()
+ {
+ if($this->_wsdlUri==='')
+ {
+ $provider=$this->getProvider();
+ $providerClass=($pos=strrpos($provider,'.'))!==false?substr($provider,$pos+1):$provider;
+ Prado::using($provider);
+ if($this->getApplication()->getMode()===TApplicationMode::Performance && ($cache=$this->getApplication()->getCache())!==null)
+ {
+ $wsdl=$cache->get(self::WSDL_CACHE_PREFIX.$providerClass);
+ if(is_string($wsdl))
+ return $wsdl;
+ Prado::using('System.3rdParty.WsdlGen.WsdlGenerator');
+ $wsdl=WsdlGenerator::generate($providerClass, $this->getUri(), $this->getEncoding());
+ $cache->set(self::WSDL_CACHE_PREFIX.$providerClass,$wsdl);
+ return $wsdl;
+ }
+ else
+ {
+ Prado::using('System.3rdParty.WsdlGen.WsdlGenerator');
+ return WsdlGenerator::generate($providerClass, $this->getUri(), $this->getEncoding());
+ }
+ }
+ else
+ return file_get_contents($this->_wsdlUri);
+ }
+
+ /**
+ * @return string the URI for WSDL
+ */
+ public function getWsdlUri()
+ {
+ if($this->_wsdlUri==='')
+ return $this->getRequest()->getBaseUrl().$this->getService()->constructUrl($this->getID().'.wsdl',false);
+ else
+ return $this->_wsdlUri;
+ }
+
+ /**
+ * @param string the URI for WSDL
+ */
+ public function setWsdlUri($value)
+ {
+ $this->_wsdlUri=$value;
+ }
+
+ /**
+ * @return string the URI for the SOAP service
+ */
+ public function getUri()
+ {
+ if($this->_uri==='')
+ return $this->getRequest()->getBaseUrl().$this->getService()->constructUrl($this->getID(),false);
+ else
+ return $this->_uri;
+ }
+
+ /**
+ * @param string the URI for the SOAP service
+ */
+ public function setUri($uri)
+ {
+ $this->_uri=$uri;
+ }
+
+ /**
+ * @return string the SOAP provider class (in namespace format)
+ */
+ public function getProvider()
+ {
+ return $this->_provider;
+ }
+
+ /**
+ * @param string the SOAP provider class (in namespace format)
+ */
+ public function setProvider($provider)
+ {
+ $this->_provider=$provider;
+ }
+
+ /**
+ * @return string SOAP version, defaults to empty (meaning not set).
+ */
+ public function getVersion()
+ {
+ return $this->_version;
+ }
+
+ /**
+ * @param string SOAP version, either '1.1' or '1.2'
+ * @throws TInvalidDataValueException if neither '1.1' nor '1.2'
+ */
+ public function setVersion($value)
+ {
+ if($value==='1.1' || $value==='1.2' || $value==='')
+ $this->_version=$value;
+ else
+ throw new TInvalidDataValueException('soapserver_version_invalid',$value);
+ }
+
+ /**
+ * @return string actor of the SOAP service
+ */
+ public function getActor()
+ {
+ return $this->_actor;
+ }
+
+ /**
+ * @param string actor of the SOAP service
+ */
+ public function setActor($value)
+ {
+ $this->_actor=$value;
+ }
+
+ /**
+ * @return string encoding of the SOAP service
+ */
+ public function getEncoding()
+ {
+ return $this->_encoding;
+ }
+
+ /**
+ * @param string encoding of the SOAP service
+ */
+ public function setEncoding($value)
+ {
+ $this->_encoding=$value;
+ }
+
+ /**
+ * @return boolean whether the SOAP service is persistent within session. Defaults to false.
+ */
+ public function getSessionPersistent()
+ {
+ return $this->_persistent;
+ }
+
+ /**
+ * @param boolean whether the SOAP service is persistent within session.
+ */
+ public function setSessionPersistent($value)
+ {
+ $this->_persistent=TPropertyValue::ensureBoolean($value);
+ }
+
+ /**
+ * @return string comma delimit list of complex type classes.
+ */
+ public function getClassMaps()
+ {
+ return $this->_classMap;
+ }
+
+ /**
+ * @return string comma delimit list of class names
+ */
+ public function setClassMaps($classes)
+ {
+ $this->_classMap = $classes;
+ }
+} \ No newline at end of file
diff --git a/framework/Web/Services/TSoapService.php b/framework/Web/Services/TSoapService.php
index c928dc06..7342eb3d 100644
--- a/framework/Web/Services/TSoapService.php
+++ b/framework/Web/Services/TSoapService.php
@@ -284,339 +284,4 @@ class TSoapService extends TService
$server->run();
}
}
-}
-
-
-/**
- * TSoapServer class.
- *
- * TSoapServer is a wrapper of the PHP SoapServer class.
- * It associates a SOAP provider class to the SoapServer object.
- * It also manages the URI for the SOAP service and WSDL.
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @package System.Web.Services
- * @since 3.1
- */
-class TSoapServer extends TApplicationComponent
-{
- const WSDL_CACHE_PREFIX='wsdl.';
-
- private $_id;
- private $_provider;
-
- private $_version='';
- private $_actor='';
- private $_encoding='';
- private $_uri='';
- private $_classMap;
- private $_persistent=false;
- private $_wsdlUri='';
-
- private $_requestedMethod;
-
- private $_server;
-
- /**
- * @return string the ID of the SOAP server
- */
- public function getID()
- {
- return $this->_id;
- }
-
- /**
- * @param string the ID of the SOAP server
- * @throws TInvalidDataValueException if the ID ends with '.wsdl'.
- */
- public function setID($id)
- {
- if(strrpos($this->_id,'.wsdl')===strlen($this->_id)-5)
- throw new TInvalidDataValueException('soapserver_id_invalid',$id);
- $this->_id=$id;
- }
-
- /**
- * Handles the SOAP request.
- */
- public function run()
- {
- if(($provider=$this->getProvider())!==null)
- {
- Prado::using($provider);
- $providerClass=($pos=strrpos($provider,'.'))!==false?substr($provider,$pos+1):$provider;
- $this->guessMethodCallRequested($providerClass);
- $server=$this->createServer();
- $server->setClass($providerClass, $this);
- if($this->_persistent)
- $server->setPersistence(SOAP_PERSISTENCE_SESSION);
- }
- else
- $server=$this->createServer();
- try
- {
- $server->handle();
- }
- catch (Exception $e)
- {
- if($this->getApplication()->getMode()===TApplicationMode::Debug)
- $this->fault($e->getMessage(), $e->__toString());
- else
- $this->fault($e->getMessage());
- }
- }
-
- /**
- * Generate a SOAP fault message.
- * @param string message title
- * @param mixed message details
- * @param string message code, defalt is 'SERVER'.
- * @param string actors
- * @param string message name
- */
- public function fault($title, $details='', $code='SERVER', $actor='', $name='')
- {
- Prado::trace('SOAP-Fault '.$code. ' '.$title.' : '.$details, 'System.Web.Services.TSoapService');
- $this->_server->fault($code, $title, $actor, $details, $name);
- }
-
- /**
- * Guess the SOAP method request from the actual SOAP message
- *
- * @param string $class current handler class.
- */
- protected function guessMethodCallRequested($class)
- {
- $namespace = $class.'wsdl';
- $message = file_get_contents("php://input");
- $matches= array();
- if(preg_match('/xmlns:([^=]+)="urn:'.$namespace.'"/', $message, $matches))
- {
- if(preg_match('/<'.$matches[1].':([a-zA-Z_]+[a-zA-Z0-9_]+)/', $message, $method))
- {
- $this->_requestedMethod = $method[1];
- }
- }
- }
-
- /**
- * Soap method guessed from the SOAP message received.
- * @return string soap method request, null if not found.
- */
- public function getRequestedMethod()
- {
- return $this->_requestedMethod;
- }
-
- /**
- * Creates the SoapServer instance.
- * @return SoapServer
- */
- protected function createServer()
- {
- if($this->_server===null)
- {
- if($this->getApplication()->getMode()===TApplicationMode::Debug)
- ini_set("soap.wsdl_cache_enabled",0);
- $this->_server = new SoapServer($this->getWsdlUri(),$this->getOptions());
- }
- return $this->_server;
- }
-
- /**
- * @return array options for creating SoapServer instance
- */
- protected function getOptions()
- {
- $options=array();
- if($this->_version==='1.1')
- $options['soap_version']=SOAP_1_1;
- else if($this->_version==='1.2')
- $options['soap_version']=SOAP_1_2;
- if(!empty($this->_actor))
- $options['actor']=$this->_actor;
- if(!empty($this->_encoding))
- $options['encoding']=$this->_encoding;
- if(!empty($this->_uri))
- $options['uri']=$this->_uri;
- if(is_string($this->_classMap))
- {
- foreach(preg_split('/\s*,\s*/', $this->_classMap) as $className)
- $options['classmap'][$className]=$className; //complex type uses the class name in the wsdl
- }
- return $options;
- }
-
- /**
- * Returns the WSDL content of the SOAP server.
- * If {@link getWsdlUri WsdlUri} is set, its content will be returned.
- * If not, the {@link setProvider Provider} class will be investigated
- * and the WSDL will be automatically genearted.
- * @return string the WSDL content of the SOAP server
- */
- public function getWsdl()
- {
- if($this->_wsdlUri==='')
- {
- $provider=$this->getProvider();
- $providerClass=($pos=strrpos($provider,'.'))!==false?substr($provider,$pos+1):$provider;
- Prado::using($provider);
- if($this->getApplication()->getMode()===TApplicationMode::Performance && ($cache=$this->getApplication()->getCache())!==null)
- {
- $wsdl=$cache->get(self::WSDL_CACHE_PREFIX.$providerClass);
- if(is_string($wsdl))
- return $wsdl;
- Prado::using('System.3rdParty.WsdlGen.WsdlGenerator');
- $wsdl=WsdlGenerator::generate($providerClass, $this->getUri(), $this->getEncoding());
- $cache->set(self::WSDL_CACHE_PREFIX.$providerClass,$wsdl);
- return $wsdl;
- }
- else
- {
- Prado::using('System.3rdParty.WsdlGen.WsdlGenerator');
- return WsdlGenerator::generate($providerClass, $this->getUri(), $this->getEncoding());
- }
- }
- else
- return file_get_contents($this->_wsdlUri);
- }
-
- /**
- * @return string the URI for WSDL
- */
- public function getWsdlUri()
- {
- if($this->_wsdlUri==='')
- return $this->getRequest()->getBaseUrl().$this->getService()->constructUrl($this->getID().'.wsdl',false);
- else
- return $this->_wsdlUri;
- }
-
- /**
- * @param string the URI for WSDL
- */
- public function setWsdlUri($value)
- {
- $this->_wsdlUri=$value;
- }
-
- /**
- * @return string the URI for the SOAP service
- */
- public function getUri()
- {
- if($this->_uri==='')
- return $this->getRequest()->getBaseUrl().$this->getService()->constructUrl($this->getID(),false);
- else
- return $this->_uri;
- }
-
- /**
- * @param string the URI for the SOAP service
- */
- public function setUri($uri)
- {
- $this->_uri=$uri;
- }
-
- /**
- * @return string the SOAP provider class (in namespace format)
- */
- public function getProvider()
- {
- return $this->_provider;
- }
-
- /**
- * @param string the SOAP provider class (in namespace format)
- */
- public function setProvider($provider)
- {
- $this->_provider=$provider;
- }
-
- /**
- * @return string SOAP version, defaults to empty (meaning not set).
- */
- public function getVersion()
- {
- return $this->_version;
- }
-
- /**
- * @param string SOAP version, either '1.1' or '1.2'
- * @throws TInvalidDataValueException if neither '1.1' nor '1.2'
- */
- public function setVersion($value)
- {
- if($value==='1.1' || $value==='1.2' || $value==='')
- $this->_version=$value;
- else
- throw new TInvalidDataValueException('soapserver_version_invalid',$value);
- }
-
- /**
- * @return string actor of the SOAP service
- */
- public function getActor()
- {
- return $this->_actor;
- }
-
- /**
- * @param string actor of the SOAP service
- */
- public function setActor($value)
- {
- $this->_actor=$value;
- }
-
- /**
- * @return string encoding of the SOAP service
- */
- public function getEncoding()
- {
- return $this->_encoding;
- }
-
- /**
- * @param string encoding of the SOAP service
- */
- public function setEncoding($value)
- {
- $this->_encoding=$value;
- }
-
- /**
- * @return boolean whether the SOAP service is persistent within session. Defaults to false.
- */
- public function getSessionPersistent()
- {
- return $this->_persistent;
- }
-
- /**
- * @param boolean whether the SOAP service is persistent within session.
- */
- public function setSessionPersistent($value)
- {
- $this->_persistent=TPropertyValue::ensureBoolean($value);
- }
-
- /**
- * @return string comma delimit list of complex type classes.
- */
- public function getClassMaps()
- {
- return $this->_classMap;
- }
-
- /**
- * @return string comma delimit list of class names
- */
- public function setClassMaps($classes)
- {
- $this->_classMap = $classes;
- }
-}
-
+} \ No newline at end of file
diff --git a/framework/Web/Services/TXmlRpcProtocol.php b/framework/Web/Services/TXmlRpcProtocol.php
new file mode 100644
index 00000000..4e287675
--- /dev/null
+++ b/framework/Web/Services/TXmlRpcProtocol.php
@@ -0,0 +1,131 @@
+<?php
+/**
+ * @author Robin J. Rogge <rrogge@bigpoint.net>
+ * @link http://www.pradosoft.com/
+ * @copyright 2010 Bigpoint GmbH
+ * @license http://www.pradosoft.com/license/
+ * @version $Id$
+ * @since 3.2
+ * @package System.Web.Services
+ */
+
+/**
+ * TXmlRpcProtocol class
+ *
+ * TXmlRpcProtocol is a class that implements XML-Rpc protocol in {@link TRpcService}.
+ * It's basically a wrapper to the xmlrpc_server_* family of php methods.
+ *
+ * @author Robin J. Rogge <rrogge@bigpoint.net>
+ * @version $Id$
+ * @package System.Web.Services
+ * @since 3.2
+ */
+class TXmlRpcProtocol extends TRpcProtocol
+{
+ /**
+ * @var XML RPC server resource
+ */
+ private $_xmlrpcServer;
+
+ // magics
+
+ /**
+ * Constructor
+ */
+ public function __construct()
+ {
+ $this->_xmlrpcServer = xmlrpc_server_create();
+ }
+
+ /**
+ * Destructor
+ */
+ public function __destruct()
+ {
+ xmlrpc_server_destroy($this->_xmlrpcServer);
+ }
+
+ // methods
+
+ /**
+ * Registers a new RPC method and handler details
+ * @param string $methodName
+ * @param array $handlerDetails containing the callback handler
+ */
+ public function addMethod($methodName, $methodDetails)
+ {
+ parent::addMethod($methodName, $methodDetails);
+
+ xmlrpc_server_register_method($this->_xmlrpcServer, $methodName, array($this, 'callApiMethod'));
+ }
+
+ // methods
+
+ /**
+ * Handles the RPC request
+ * @param string $requestPayload
+ * @return string XML RPC response
+ */
+ public function callMethod($requestPayload)
+ {
+ try
+ {
+ return xmlrpc_server_call_method($this->_xmlrpcServer, $requestPayload, null);
+ }
+ catch(TRpcException $e)
+ {
+ return $this->createErrorResponse($e);
+ }
+ catch(THttpException $e)
+ {
+ throw $e;
+ }
+ catch(Exception $e)
+ {
+ return $this->createErrorResponse(new TRpcException('An internal error occured'));
+ }
+ }
+
+ /**
+ * Turns the given exception into an XML RPC fault
+ * @param TRpcException $exception
+ * @return string XML RPC fault
+ */
+ public function createErrorResponse(TRpcException $exception)
+ {
+ return $this->encode(array(
+ 'faultCode' => $exception->getCode(),
+ 'faultString' => $exception->getMessage()
+ ));
+ }
+
+ /**
+ * Sets the correct response headers
+ * @param THttpResponse $response
+ */
+ public function createResponseHeaders($response)
+ {
+ $response->setContentType('text/xml');
+ $response->setCharset('UTF-8');
+ }
+
+ /**
+ * Decodes XML encoded data into PHP data
+ * @param string $data in XML format
+ * @return array PHP data
+ */
+ public function decode($data)
+ {
+ return xmlrpc_decode($data);
+ }
+
+ /**
+ * Encodes PHP data into XML data
+ * @param mixed PHP data
+ * @return string XML encoded PHP data
+ */
+ public function encode($data)
+ {
+ return xmlrpc_encode($data);
+ }
+} \ No newline at end of file