Merge branch 'wip-MDL-34234-m24' of git://github.com/samhemelryk/moodle
[moodle.git] / webservice / amf / locallib.php
blobcd0bd10dd49878d619489924735bd600b0f8bf49
1 <?php
2 // This file is part of Moodle - http://moodle.org/
3 //
4 // Moodle is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // Moodle is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
18 /**
19 * AMF web service implementation classes and methods.
21 * @package webservice_amf
22 * @copyright 2009 Petr Skodak
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
26 require_once("$CFG->dirroot/webservice/lib.php");
27 require_once( "{$CFG->dirroot}/webservice/amf/introspector.php");
28 require_once 'Zend/Amf/Server.php';
30 /**
31 * Exception indicating an invalid return value from a function.
33 * Used when an externallib function does not return values of the expected structure.
35 * @package webservice_amf
36 * @copyright 2010 Jamie Pratt
37 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
39 class invalid_return_value_exception extends moodle_exception {
41 /**
42 * Constructor
44 * @param string $debuginfo some detailed information
46 function __construct($debuginfo=null) {
47 parent::__construct('invalidreturnvalue', 'webservice_amf', '', $debuginfo, $debuginfo);
51 /**
52 * AMF service server implementation.
54 * @package webservice_amf
55 * @copyright 2009 Petr Skodak
56 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
58 class webservice_amf_server extends webservice_zend_server {
60 /**
61 * Contructor
63 * @param integer $authmethod authentication method - one of WEBSERVICE_AUTHMETHOD_*
65 public function __construct($authmethod) {
66 parent::__construct($authmethod, 'Moodle_Amf_Server');
67 $this->wsname = 'amf';
70 /**
71 * Load virtual class needed for Zend api
73 protected function init_service_class(){
74 parent::init_service_class();
75 //allow access to data about methods available.
76 $this->zend_server->setClass( "MethodDescriptor" );
77 MethodDescriptor::$classnametointrospect = $this->service_class;
80 /**
81 * Get the generated web service function code.
83 * @param stdClass $function contains function name and class name
84 * @param array $params all the function parameters
85 * @return string the generate web service function code
87 protected function service_class_method_body($function, $params){
88 //cast the param from object to array (validate_parameters except array only)
89 $castingcode = '';
90 if ($params){
91 $paramstocast = explode(',', $params);
92 foreach ($paramstocast as $paramtocast) {
93 $paramtocast = trim($paramtocast);
94 $castingcode .= $paramtocast .
95 '=webservice_zend_server::cast_objects_to_array('.$paramtocast.');';
100 $externallibcall = $function->classname.'::'.$function->methodname.'('.$params.')';
101 $descriptionmethod = $function->methodname.'_returns()';
102 $callforreturnvaluedesc = $function->classname.'::'.$descriptionmethod;
103 return $castingcode .
104 ' return webservice_amf_server::validate_and_cast_values('.$callforreturnvaluedesc.', '.$externallibcall.');';
108 * Validates submitted value, comparing it to a description. If anything is incorrect
109 * invalid_return_value_exception is thrown. Also casts the values to the type specified in
110 * the description.
112 * @param external_description $description description of parameters or null if no return value
113 * @param mixed $value the actual values
114 * @return mixed params with added defaults for optional items
115 * @throws invalid_return_value_exception
117 public static function validate_and_cast_values($description, $value) {
118 if (is_null($description)){
119 return;
121 if ($description instanceof external_value) {
122 if (is_array($value) or is_object($value)) {
123 throw new invalid_return_value_exception('Scalar type expected, array or object received.');
126 if ($description->type == PARAM_BOOL) {
127 // special case for PARAM_BOOL - we want true/false instead of the usual 1/0 - we can not be too strict here ;-)
128 if (is_bool($value) or $value === 0 or $value === 1 or $value === '0' or $value === '1') {
129 return (bool)$value;
132 return validate_param($value, $description->type, $description->allownull, 'Invalid external api parameter');
134 } else if ($description instanceof external_single_structure) {
135 if (!is_array($value)) {
136 throw new invalid_return_value_exception('Only arrays accepted.');
138 $result = array();
139 foreach ($description->keys as $key=>$subdesc) {
140 if (!array_key_exists($key, $value)) {
141 if ($subdesc->required == VALUE_REQUIRED) {
142 throw new invalid_return_value_exception('Missing required key in single structure: '.$key);
144 if ($subdesc instanceof external_value) {
145 if ($subdesc->required == VALUE_DEFAULT) {
146 $result[$key] = self::validate_and_cast_values($subdesc, $subdesc->default);
149 } else {
150 $result[$key] = self::validate_and_cast_values($subdesc, $value[$key]);
152 unset($value[$key]);
155 return (object)$result;
157 } else if ($description instanceof external_multiple_structure) {
158 if (!is_array($value)) {
159 throw new invalid_return_value_exception('Only arrays accepted.');
161 $result = array();
162 foreach ($value as $param) {
163 $result[] = self::validate_and_cast_values($description->content, $param);
165 return $result;
167 } else {
168 throw new invalid_return_value_exception('Invalid external api description.');
173 * Set up zend service class
175 protected function init_zend_server() {
176 parent::init_zend_server();
177 $this->zend_server->setProduction(false); //set to false for development mode
178 //(complete error message displayed into your AMF client)
183 * Zend Amf server with a different fault management
185 * @package webservice_amf
186 * @copyright 2010 Jamie Pratt
187 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
189 class Moodle_Amf_Server extends Zend_Amf_Server{
192 * Raise a server fault
194 * @param string|Exception $fault
195 * @param int $code fault code
197 public function fault($fault = null, $code = 404)
199 if (!$fault instanceof Exception) {
200 $fault = new Exception($fault);
202 $request = $this->getRequest();
203 // Get the object encoding of the request.
204 $objectEncoding = $request->getObjectEncoding();
206 // create a response object to place the output from the services.
207 $response = $this->getResponse();
209 // set reponse encoding
210 $response->setObjectEncoding($objectEncoding);
212 $responseBody = $request->getAmfBodies();
214 foreach($responseBody as $body){
215 $return = $this->_errorMessage($objectEncoding, $fault->getMessage(),
216 $fault->getMessage(), $fault->getTraceAsString(),$fault->getCode(), $fault->getLine());
217 $responseType = Zend_AMF_Constants::STATUS_METHOD;
220 $responseURI = $body->getResponseURI() . $responseType;
221 $newBody = new Zend_Amf_Value_MessageBody($responseURI, null, $return);
222 $response->addAmfBody($newBody);
224 $response->finalize();
225 echo $response;