Moodle  2.2.1
http://www.collinsharper.com
C:/xampp/htdocs/moodle/webservice/amf/locallib.php
Go to the documentation of this file.
00001 <?php
00002 
00003 // This file is part of Moodle - http://moodle.org/
00004 //
00005 // Moodle is free software: you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License as published by
00007 // the Free Software Foundation, either version 3 of the License, or
00008 // (at your option) any later version.
00009 //
00010 // Moodle is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
00017 
00026 require_once("$CFG->dirroot/webservice/lib.php");
00027 require_once( "{$CFG->dirroot}/webservice/amf/introspector.php");
00028 require_once 'Zend/Amf/Server.php';
00033 class invalid_return_value_exception extends moodle_exception {
00038     function __construct($debuginfo=null) {
00039         parent::__construct('invalidreturnvalue', 'webservice_amf', '', $debuginfo, $debuginfo);
00040     }
00041 }
00042 
00047 class webservice_amf_server extends webservice_zend_server {
00052     public function __construct($authmethod) {
00053         parent::__construct($authmethod, 'Moodle_Amf_Server');
00054         $this->wsname = 'amf';
00055     }
00056     protected function init_service_class(){
00057         parent::init_service_class();
00058         //allow access to data about methods available.
00059         $this->zend_server->setClass( "MethodDescriptor" );
00060         MethodDescriptor::$classnametointrospect = $this->service_class;
00061     }
00062     
00063     protected function service_class_method_body($function, $params){
00064         //cast the param from object to array (validate_parameters except array only)
00065         $castingcode = '';
00066         if ($params){
00067             $paramstocast = explode(',', $params);
00068             foreach ($paramstocast as $paramtocast) {
00069                 $paramtocast = trim($paramtocast);
00070                 $castingcode .= $paramtocast .
00071                 '=webservice_zend_server::cast_objects_to_array('.$paramtocast.');';
00072         }
00073 
00074         }
00075 
00076         $externallibcall = $function->classname.'::'.$function->methodname.'('.$params.')';
00077         $descriptionmethod = $function->methodname.'_returns()';
00078         $callforreturnvaluedesc = $function->classname.'::'.$descriptionmethod;
00079         return $castingcode . 
00080 '        return webservice_amf_server::validate_and_cast_values('.$callforreturnvaluedesc.', '.$externallibcall.');';
00081     }
00092     public static function validate_and_cast_values($description, $value) {
00093         if (is_null($description)){
00094             return;
00095         }
00096         if ($description instanceof external_value) {
00097             if (is_array($value) or is_object($value)) {
00098                 throw new invalid_return_value_exception('Scalar type expected, array or object received.');
00099             }
00100 
00101             if ($description->type == PARAM_BOOL) {
00102                 // special case for PARAM_BOOL - we want true/false instead of the usual 1/0 - we can not be too strict here ;-)
00103                 if (is_bool($value) or $value === 0 or $value === 1 or $value === '0' or $value === '1') {
00104                     return (bool)$value;
00105                 }
00106             }
00107             return validate_param($value, $description->type, $description->allownull, 'Invalid external api parameter');
00108 
00109         } else if ($description instanceof external_single_structure) {
00110             if (!is_array($value)) {
00111                 throw new invalid_return_value_exception('Only arrays accepted.');
00112             }
00113             $result = array();
00114             foreach ($description->keys as $key=>$subdesc) {
00115                 if (!array_key_exists($key, $value)) {
00116                     if ($subdesc->required == VALUE_REQUIRED) {
00117                         throw new invalid_return_value_exception('Missing required key in single structure: '.$key);
00118                     }
00119                     if ($subdesc instanceof external_value) {
00120                             if ($subdesc->required == VALUE_DEFAULT) {
00121                                 $result[$key] = self::validate_and_cast_values($subdesc, $subdesc->default);
00122                             }
00123                     }
00124                 } else {
00125                     $result[$key] = self::validate_and_cast_values($subdesc, $value[$key]);
00126                 }
00127                 unset($value[$key]);
00128             }
00129 /*          Was decided that extra keys should just be ignored and not returned.
00130  *          if (!empty($value)) {
00131                 throw new invalid_return_value_exception('Unexpected keys detected in parameter array.');
00132             }*/
00133             return (object)$result;
00134 
00135         } else if ($description instanceof external_multiple_structure) {
00136             if (!is_array($value)) {
00137                 throw new invalid_return_value_exception('Only arrays accepted.');
00138             }
00139             $result = array();
00140             foreach ($value as $param) {
00141                 $result[] = self::validate_and_cast_values($description->content, $param);
00142             }
00143             return $result;
00144 
00145         } else {
00146             throw new invalid_return_value_exception('Invalid external api description.');
00147         }
00148     }    
00149     
00154     protected function init_zend_server() {
00155         parent::init_zend_server();
00156         $this->zend_server->setProduction(false); //set to false for development mode
00157                                                  //(complete error message displayed into your AMF client)
00158         // TODO: add some exception handling
00159     }
00160 
00161 
00162 }
00163 class Moodle_Amf_Server extends Zend_Amf_Server{
00170     public function fault($fault = null, $code = 404)
00171     {
00172         if (!$fault instanceof Exception) {
00173             $fault = new Exception($fault);
00174         }
00175         $request = $this->getRequest();
00176         // Get the object encoding of the request.
00177         $objectEncoding = $request->getObjectEncoding();
00178 
00179         // create a response object to place the output from the services.
00180         $response = $this->getResponse();
00181 
00182         // set reponse encoding
00183         $response->setObjectEncoding($objectEncoding);
00184         
00185         $responseBody = $request->getAmfBodies();
00186 
00187         foreach($responseBody as $body){
00188             $return = $this->_errorMessage($objectEncoding, $fault->getMessage(), 
00189                 $fault->getMessage(), $fault->getTraceAsString(),$fault->getCode(),  $fault->getLine());
00190             $responseType = Zend_AMF_Constants::STATUS_METHOD;
00191     
00192     
00193             $responseURI = $body->getResponseURI() . $responseType;
00194             $newBody     = new Zend_Amf_Value_MessageBody($responseURI, null, $return);
00195             $response->addAmfBody($newBody);
00196         }
00197         $response->finalize();
00198         echo $response;
00199     }
00200 }
00201 
00202 // TODO: implement AMF test client somehow, maybe we could use moodle form to feed the data to the flash app somehow
 All Data Structures Namespaces Files Functions Variables Enumerations