Example #1
0
 /**
  * Add a Single or Multiple Functions to the WSDL
  *
  * @param string $function Function Name
  * @param string $namespace Function namespace - Not Used
  * @return Zend_Soap_AutoDiscover
  */
 public function addFunction($function, $namespace = '')
 {
     static $port;
     static $operation;
     static $binding;
     if (!is_array($function)) {
         $function = (array) $function;
     }
     $uri = $this->getUri();
     if (!$this->_wsdl instanceof Zend_Soap_Wsdl) {
         $parts = explode('.', basename($_SERVER['SCRIPT_NAME']));
         $name = $parts[0];
         $wsdl = new Zend_Soap_Wsdl($name, $uri, $this->_strategy);
         // The wsdl:types element must precede all other elements (WS-I Basic Profile 1.1 R2023)
         $wsdl->addSchemaTypeSection();
         $port = $wsdl->addPortType($name . 'Port');
         $binding = $wsdl->addBinding($name . 'Binding', 'tns:' . $name . 'Port');
         $wsdl->addSoapBinding($binding, $this->_bindingStyle['style'], $this->_bindingStyle['transport']);
         $wsdl->addService($name . 'Service', $name . 'Port', 'tns:' . $name . 'Binding', $uri);
     } else {
         $wsdl = $this->_wsdl;
     }
     foreach ($function as $func) {
         $method = $this->_reflection->reflectFunction($func);
         $this->_addFunctionToWsdl($method, $wsdl, $port, $binding);
     }
     $this->_wsdl = $wsdl;
     return $this;
 }
Example #2
0
 /**
  * Add a Single or Multiple Functions to the WSDL
  *
  * @param string $function Function Name
  * @param string $namespace Function namespace - Not Used
  */
 public function addFunction($function, $namespace = '')
 {
     static $port;
     static $operation;
     static $binding;
     if (!is_array($function)) {
         $function = (array) $function;
     }
     $uri = $this->getUri();
     if (!$this->_wsdl instanceof Zend_Soap_Wsdl) {
         $parts = explode('.', basename($_SERVER['SCRIPT_NAME']));
         $name = $parts[0];
         $wsdl = new Zend_Soap_Wsdl($name, $uri, $this->_strategy);
         $port = $wsdl->addPortType($name . 'Port');
         $binding = $wsdl->addBinding($name . 'Binding', 'tns:' . $name . 'Port');
         $wsdl->addSoapBinding($binding, $this->_bindingStyle['style'], $this->_bindingStyle['transport']);
         $wsdl->addService($name . 'Service', $name . 'Port', 'tns:' . $name . 'Binding', $uri);
     } else {
         $wsdl = $this->_wsdl;
     }
     foreach ($function as $func) {
         $method = $this->_reflection->reflectFunction($func);
         foreach ($method->getPrototypes() as $prototype) {
             $args = array();
             foreach ($prototype->getParameters() as $param) {
                 $args[$param->getName()] = $wsdl->getType($param->getType());
             }
             $message = $wsdl->addMessage($method->getName() . 'Request', $args);
             $desc = $method->getDescription();
             if (strlen($desc) > 0) {
                 //$wsdl->addDocumentation($message, $desc);
             }
             if ($prototype->getReturnType() != "void") {
                 if ($this->_responseMessageReturnNameCompability === true) {
                     $returnName = "return";
                 } else {
                     $returnName = $method->getName() . 'Return';
                 }
                 $message = $wsdl->addMessage($method->getName() . 'Response', array($returnName => $wsdl->getType($prototype->getReturnType())));
             }
             /* <wsdl:portType>'s */
             $portOperation = $wsdl->addPortOperation($port, $method->getName(), 'tns:' . $method->getName() . 'Request', 'tns:' . $method->getName() . 'Response');
             if (strlen($desc) > 0) {
                 //$wsdl->addDocumentation($portOperation, $desc);
             }
             /* </wsdl:portType>'s */
             /* <wsdl:binding>'s */
             $operation = $wsdl->addBindingOperation($binding, $method->getName(), $this->_operationBodyStyle, $this->_operationBodyStyle);
             $wsdl->addSoapOperation($operation, $uri->getUri() . '#' . $method->getName());
             /* </wsdl:binding>'s */
             $this->_functions[] = $method->getName();
             // We will only add one prototype
             break;
         }
     }
     $this->_wsdl = $wsdl;
 }
Example #3
0
 /**
  * Add a Single or Multiple Functions to the WSDL
  *
  * @param string $function Function Name
  * @param string $namespace Function namespace - Not Used
  */
 public function addFunction($function, $namespace = '')
 {
     static $port;
     static $operation;
     static $binding;
     if (!is_array($function)) {
         $function = (array) $function;
     }
     $uri = Zend_Uri::factory('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['SCRIPT_NAME']);
     if (!$this->_wsdl instanceof Zend_Soap_Wsdl) {
         $parts = explode('.', basename($_SERVER['SCRIPT_NAME']));
         $name = $parts[0];
         $wsdl = new Zend_Soap_Wsdl($name, $uri, $this->_extractComplexTypes);
         $port = $wsdl->addPortType($name . 'Port');
         $binding = $wsdl->addBinding($name . 'Binding', 'tns:' . $name . 'Port');
         $wsdl->addSoapBinding($binding, 'rpc');
         $wsdl->addService($name . 'Service', $name . 'Port', 'tns:' . $name . 'Binding', $uri);
     } else {
         $wsdl = $this->_wsdl;
     }
     foreach ($function as $func) {
         $method = $this->_reflection->reflectFunction($func);
         foreach ($method->getPrototypes() as $prototype) {
             $args = array();
             foreach ($prototype->getParameters() as $param) {
                 $args[$param->getName()] = $wsdl->getType($param->getType());
             }
             $message = $wsdl->addMessage($method->getName() . 'Request', $args);
             $desc = $method->getDescription();
             if (strlen($desc) > 0) {
                 //$wsdl->addDocumentation($message, $desc);
             }
             if ($prototype->getReturnType() != "void") {
                 $message = $wsdl->addMessage($method->getName() . 'Response', array($method->getName() . 'Return' => $wsdl->getType($prototype->getReturnType())));
             }
             /* <wsdl:portType>'s */
             $portOperation = $wsdl->addPortOperation($port, $method->getName(), 'tns:' . $method->getName() . 'Request', 'tns:' . $method->getName() . 'Response');
             if (strlen($desc) > 0) {
                 //$wsdl->addDocumentation($portOperation, $desc);
             }
             /* </wsdl:portType>'s */
             /* <wsdl:binding>'s */
             $operation = $wsdl->addBindingOperation($binding, $method->getName(), array('use' => 'encoded', 'encodingStyle' => "http://schemas.xmlsoap.org/soap/encoding/"), array('use' => 'encoded', 'encodingStyle' => "http://schemas.xmlsoap.org/soap/encoding/"));
             $wsdl->addSoapOperation($binding, $uri->getUri() . '#' . $method->getName());
             /* </wsdl:binding>'s */
             $this->_functions[] = $method->getName();
             // We will only add one prototype
             break;
         }
     }
     $this->_wsdl = $wsdl;
 }
 /**
  * Implement Zend_Server_Interface::addFunction()
  *
  * @param string $function Function Name
  * @param string $namespace Function namespace (unused)
  */
 public function addFunction($function, $namespace = '')
 {
     if (!is_array($function)) {
         $function = (array) $function;
     }
     foreach ($function as $func) {
         if (is_callable($func) && !in_array($func, self::$magic_methods)) {
             $this->_functions[$func] = $this->_reflection->reflectFunction($func);
         } else {
             throw new Zend_Rest_Server_Exception("Invalid Method Added to Service.");
         }
     }
 }
Example #5
0
 /**
  * Implement Zend_Server_Interface::addFunction()
  *
  * @param string $function Function Name
  * @param string $namespace Function namespace (unused)
  */
 public function addFunction($function, $namespace = '')
 {
     if (!is_array($function)) {
         $function = (array) $function;
     }
     foreach ($function as $func) {
         if (is_callable($func) && !in_array($func, self::$magicMethods)) {
             $this->_functions[$func] = $this->_reflection->reflectFunction($func);
         } else {
             require_once PHP_LIBRARY_PATH . 'Zend/Rest/Server/Exception.php';
             throw new Zend_Rest_Server_Exception("Invalid Method Added to Service.");
         }
     }
 }
Example #6
0
 public function setClass($class, $namespace = '', $argv = null)
 {
     if (is_string($class) && !class_exists($class)) {
         throw new Cosmos_Api_Server_Exception('Invalid method class', 610);
     }
     $argv = null;
     if (2 < func_num_args()) {
         $argv = func_get_args();
         $argv = array_slice($argv, 2);
     }
     $dispatchable = Zend_Server_Reflection::reflectClass($class, $argv, $namespace);
     foreach ($dispatchable->getMethods() as $reflection) {
         $this->_buildSignature($reflection, $class);
     }
 }
Example #7
0
 public function setClass($class, $namespace = '', $argv = null)
 {
     if (is_string($class) && class_exists($class) || is_object($class)) {
         // Get args.
         $argv = null;
         if (2 < func_num_args()) {
             $argv = array_slice(func_get_args(), 2);
         }
         // Get namespace.
         if ($namespace == '') {
             $namespace = is_object($class) ? get_class($class) : $class;
         }
         // Validate namespace.
         if (!new $namespace() instanceof phpMyWave_AbstractRobot) {
             throw new Exception('Invalid method or class; must be instace of phpMyWave_AbstractRobot');
         }
         // Reflect class.
         $this->_robots[] = Zend_Server_Reflection::reflectClass($class, $argv, $namespace);
     } else {
         throw new Exception('Invalid method or class; must be a classname or object');
     }
     return $this;
 }
Example #8
0
 /**
  * Attach a function to the server
  *
  * Additional arguments to pass to the function at dispatch may be passed;
  * any arguments following the namespace will be aggregated and passed at
  * dispatch time.
  *
  * @param  string|array $function Valid callback
  * @param  string $namespace Optional namespace prefix
  * @return Zend_Amf_Server
  * @throws Zend_Amf_Server_Exception
  */
 public function addFunction($function, $namespace = '')
 {
     if (!is_string($function) && !is_array($function)) {
         require_once 'Zend/Amf/Server/Exception.php';
         throw new Zend_Amf_Server_Exception('Unable to attach function');
     }
     $argv = null;
     if (2 < func_num_args()) {
         $argv = array_slice(func_get_args(), 2);
     }
     $function = (array) $function;
     foreach ($function as $func) {
         if (!is_string($func) || !function_exists($func)) {
             require_once 'Zend/Amf/Server/Exception.php';
             throw new Zend_Amf_Server_Exception('Unable to attach function');
         }
         $this->_methods[] = Zend_Server_Reflection::reflectFunction($func, $argv, $namespace);
     }
     $this->_buildDispatchTable();
     return $this;
 }
 /**
  * reflectFunction() test; test namespaces
  */
 public function testReflectFunction2()
 {
     $reflection = Zend_Server_Reflection::reflectFunction('Zend_Server_Reflection_testFunction', false, 'zsr');
     $this->assertEquals('zsr', $reflection->getNamespace());
 }
Example #10
0
 /**
  * Create XML definition on an AMF service class
  * 
  * @param  string $serviceClass Service class name
  * @param  array $options invocation options
  * @return string XML with service class introspection
  */
 public function introspect($serviceClass, $options = array())
 {
     $this->_options = $options;
     if (strpbrk($serviceClass, '\\/<>')) {
         return $this->_returnError('Invalid service name');
     }
     // Transform com.foo.Bar into com_foo_Bar
     $serviceClass = str_replace('.', '_', $serviceClass);
     // Introspect!
     if (!class_exists($serviceClass)) {
         // require_once 'Zend/Loader.php';
         Zend_Loader::loadClass($serviceClass, $this->_getServicePath());
     }
     $serv = $this->_xml->createElement('service-description');
     $serv->setAttribute('xmlns', 'http://ns.adobe.com/flex/service-description/2008');
     $this->_types = $this->_xml->createElement('types');
     $this->_ops = $this->_xml->createElement('operations');
     $r = Zend_Server_Reflection::reflectClass($serviceClass);
     $this->_addService($r, $this->_ops);
     $serv->appendChild($this->_types);
     $serv->appendChild($this->_ops);
     $this->_xml->appendChild($serv);
     return $this->_xml->saveXML();
 }
Example #11
0
/**
 * upgrades the mnet rpc definitions for the given component.
 * this method doesn't return status, an exception will be thrown in the case of an error
 *
 * @param string $component the plugin to upgrade, eg auth_mnet
 */
function upgrade_plugin_mnet_functions($component) {
    global $DB, $CFG;

    list($type, $plugin) = core_component::normalize_component($component);
    $path = core_component::get_plugin_directory($type, $plugin);

    $publishes = array();
    $subscribes = array();
    if (file_exists($path . '/db/mnet.php')) {
        require_once($path . '/db/mnet.php'); // $publishes comes from this file
    }
    if (empty($publishes)) {
        $publishes = array(); // still need this to be able to disable stuff later
    }
    if (empty($subscribes)) {
        $subscribes = array(); // still need this to be able to disable stuff later
    }

    static $servicecache = array();

    // rekey an array based on the rpc method for easy lookups later
    $publishmethodservices = array();
    $subscribemethodservices = array();
    foreach($publishes as $servicename => $service) {
        if (is_array($service['methods'])) {
            foreach($service['methods'] as $methodname) {
                $service['servicename'] = $servicename;
                $publishmethodservices[$methodname][] = $service;
            }
        }
    }

    // Disable functions that don't exist (any more) in the source
    // Should these be deleted? What about their permissions records?
    foreach ($DB->get_records('mnet_rpc', array('pluginname'=>$plugin, 'plugintype'=>$type), 'functionname ASC ') as $rpc) {
        if (!array_key_exists($rpc->functionname, $publishmethodservices) && $rpc->enabled) {
            $DB->set_field('mnet_rpc', 'enabled', 0, array('id' => $rpc->id));
        } else if (array_key_exists($rpc->functionname, $publishmethodservices) && !$rpc->enabled) {
            $DB->set_field('mnet_rpc', 'enabled', 1, array('id' => $rpc->id));
        }
    }

    // reflect all the services we're publishing and save them
    require_once($CFG->dirroot . '/lib/zend/Zend/Server/Reflection.php');
    static $cachedclasses = array(); // to store reflection information in
    foreach ($publishes as $service => $data) {
        $f = $data['filename'];
        $c = $data['classname'];
        foreach ($data['methods'] as $method) {
            $dataobject = new stdClass();
            $dataobject->plugintype  = $type;
            $dataobject->pluginname  = $plugin;
            $dataobject->enabled     = 1;
            $dataobject->classname   = $c;
            $dataobject->filename    = $f;

            if (is_string($method)) {
                $dataobject->functionname = $method;

            } else if (is_array($method)) { // wants to override file or class
                $dataobject->functionname = $method['method'];
                $dataobject->classname     = $method['classname'];
                $dataobject->filename      = $method['filename'];
            }
            $dataobject->xmlrpcpath = $type.'/'.$plugin.'/'.$dataobject->filename.'/'.$method;
            $dataobject->static = false;

            require_once($path . '/' . $dataobject->filename);
            $functionreflect = null; // slightly different ways to get this depending on whether it's a class method or a function
            if (!empty($dataobject->classname)) {
                if (!class_exists($dataobject->classname)) {
                    throw new moodle_exception('installnosuchmethod', 'mnet', '', (object)array('method' => $dataobject->functionname, 'class' => $dataobject->classname));
                }
                $key = $dataobject->filename . '|' . $dataobject->classname;
                if (!array_key_exists($key, $cachedclasses)) { // look to see if we've already got a reflection object
                    try {
                        $cachedclasses[$key] = Zend_Server_Reflection::reflectClass($dataobject->classname);
                    } catch (Zend_Server_Reflection_Exception $e) { // catch these and rethrow them to something more helpful
                        throw new moodle_exception('installreflectionclasserror', 'mnet', '', (object)array('method' => $dataobject->functionname, 'class' => $dataobject->classname, 'error' => $e->getMessage()));
                    }
                }
                $r =& $cachedclasses[$key];
                if (!$r->hasMethod($dataobject->functionname)) {
                    throw new moodle_exception('installnosuchmethod', 'mnet', '', (object)array('method' => $dataobject->functionname, 'class' => $dataobject->classname));
                }
                // stupid workaround for zend not having a getMethod($name) function
                $ms = $r->getMethods();
                foreach ($ms as $m) {
                    if ($m->getName() == $dataobject->functionname) {
                        $functionreflect = $m;
                        break;
                    }
                }
                $dataobject->static = (int)$functionreflect->isStatic();
            } else {
                if (!function_exists($dataobject->functionname)) {
                    throw new moodle_exception('installnosuchfunction', 'mnet', '', (object)array('method' => $dataobject->functionname, 'file' => $dataobject->filename));
                }
                try {
                    $functionreflect = Zend_Server_Reflection::reflectFunction($dataobject->functionname);
                } catch (Zend_Server_Reflection_Exception $e) { // catch these and rethrow them to something more helpful
                    throw new moodle_exception('installreflectionfunctionerror', 'mnet', '', (object)array('method' => $dataobject->functionname, '' => $dataobject->filename, 'error' => $e->getMessage()));
                }
            }
            $dataobject->profile =  serialize(admin_mnet_method_profile($functionreflect));
            $dataobject->help = $functionreflect->getDescription();

            if ($record_exists = $DB->get_record('mnet_rpc', array('xmlrpcpath'=>$dataobject->xmlrpcpath))) {
                $dataobject->id      = $record_exists->id;
                $dataobject->enabled = $record_exists->enabled;
                $DB->update_record('mnet_rpc', $dataobject);
            } else {
                $dataobject->id = $DB->insert_record('mnet_rpc', $dataobject, true);
            }

            // TODO this API versioning must be reworked, here the recently processed method
            // sets the service API which may not be correct
            foreach ($publishmethodservices[$dataobject->functionname] as $service) {
                if ($serviceobj = $DB->get_record('mnet_service', array('name'=>$service['servicename']))) {
                    $serviceobj->apiversion = $service['apiversion'];
                    $DB->update_record('mnet_service', $serviceobj);
                } else {
                    $serviceobj = new stdClass();
                    $serviceobj->name        = $service['servicename'];
                    $serviceobj->description = empty($service['description']) ? '' : $service['description'];
                    $serviceobj->apiversion  = $service['apiversion'];
                    $serviceobj->offer       = 1;
                    $serviceobj->id          = $DB->insert_record('mnet_service', $serviceobj);
                }
                $servicecache[$service['servicename']] = $serviceobj;
                if (!$DB->record_exists('mnet_service2rpc', array('rpcid'=>$dataobject->id, 'serviceid'=>$serviceobj->id))) {
                    $obj = new stdClass();
                    $obj->rpcid = $dataobject->id;
                    $obj->serviceid = $serviceobj->id;
                    $DB->insert_record('mnet_service2rpc', $obj, true);
                }
            }
        }
    }
    // finished with methods we publish, now do subscribable methods
    foreach($subscribes as $service => $methods) {
        if (!array_key_exists($service, $servicecache)) {
            if (!$serviceobj = $DB->get_record('mnet_service', array('name' =>  $service))) {
                debugging("TODO: skipping unknown service $service - somebody needs to fix MDL-21993");
                continue;
            }
            $servicecache[$service] = $serviceobj;
        } else {
            $serviceobj = $servicecache[$service];
        }
        foreach ($methods as $method => $xmlrpcpath) {
            if (!$rpcid = $DB->get_field('mnet_remote_rpc', 'id', array('xmlrpcpath'=>$xmlrpcpath))) {
                $remoterpc = (object)array(
                    'functionname' => $method,
                    'xmlrpcpath' => $xmlrpcpath,
                    'plugintype' => $type,
                    'pluginname' => $plugin,
                    'enabled'    => 1,
                );
                $rpcid = $remoterpc->id = $DB->insert_record('mnet_remote_rpc', $remoterpc, true);
            }
            if (!$DB->record_exists('mnet_remote_service2rpc', array('rpcid'=>$rpcid, 'serviceid'=>$serviceobj->id))) {
                $obj = new stdClass();
                $obj->rpcid = $rpcid;
                $obj->serviceid = $serviceobj->id;
                $DB->insert_record('mnet_remote_service2rpc', $obj, true);
            }
            $subscribemethodservices[$method][] = $service;
        }
    }

    foreach ($DB->get_records('mnet_remote_rpc', array('pluginname'=>$plugin, 'plugintype'=>$type), 'functionname ASC ') as $rpc) {
        if (!array_key_exists($rpc->functionname, $subscribemethodservices) && $rpc->enabled) {
            $DB->set_field('mnet_remote_rpc', 'enabled', 0, array('id' => $rpc->id));
        } else if (array_key_exists($rpc->functionname, $subscribemethodservices) && !$rpc->enabled) {
            $DB->set_field('mnet_remote_rpc', 'enabled', 1, array('id' => $rpc->id));
        }
    }

    return true;
}
Example #12
0
 /**
  * Register a class with the server
  *
  * @param  string $class
  * @param  string $namespace Ignored
  * @param  mixed $argv Ignored
  * @return Zend_Json_Server
  */
 public function setClass($class, $namespace = '', $argv = null)
 {
     $argv = null;
     if (3 < func_num_args()) {
         $argv = func_get_args();
         $argv = array_slice($argv, 3);
     }
     // require_once 'Zend/Server/Reflection.php';
     $reflection = Zend_Server_Reflection::reflectClass($class, $argv, $namespace);
     foreach ($reflection->getMethods() as $method) {
         $definition = $this->_buildSignature($method, $class);
         $this->_addMethodServiceMap($definition);
     }
     return $this;
 }
Example #13
0
 /**
  * Register a class with the server
  * 
  * @param  string $class 
  * @param  string $namespace Ignored
  * @param  mixed $argv Ignored
  * @return Zend_Json_Server
  */
 public function setClass($class, $namespace = '', $argv = null)
 {
     require_once 'Zend/Server/Reflection.php';
     $reflection = Zend_Server_Reflection::reflectClass($class);
     foreach ($reflection->getMethods() as $method) {
         $this->_methods[$method->getName()] = $method;
         $this->_addMethodServiceMap($method);
     }
     return $this;
 }
Example #14
0
 /**
  * Attach class methods as XMLRPC method handlers
  *
  * $class may be either a class name or an object. Reflection is done on the 
  * class or object to determine the available public methods, and each is 
  * attached to the server as an available method; if a $namespace has been 
  * provided, that namespace is used to prefix the XMLRPC method names.
  *
  * Any additional arguments beyond $namespace will be passed to a method at 
  * invocation.
  *
  * @param string|object $class 
  * @param string $namespace Optional
  * @param mixed $argv Optional arguments to pass to methods
  * @return void
  * @throws Zend_XmlRpc_Server_Exception on invalid input
  */
 public function setClass($class, $namespace = '', $argv = null)
 {
     if (is_string($class) && !class_exists($class)) {
         if (!class_exists($class)) {
             throw new Zend_XmlRpc_Server_Exception('Invalid method class', 610);
         }
     }
     $argv = null;
     if (3 < func_num_args()) {
         $argv = func_get_args();
         $argv = array_slice($argv, 3);
     }
     $this->_methods[] = Zend_Server_Reflection::reflectClass($class, $argv, $namespace);
     $this->_buildDispatchTable();
 }
Example #15
0
 /**
 * Generate web service description array from the phpdoc for a given class
 * @param string $file the class file
 * @param string $class the class name
 * @return array description
 *
 *
   -------
   Example
   -------
 * Docnlock: @ subparam string $params:searches->search - the string to search
 * $params is considered as the first element, searches the second, and search the terminal
 * Except the terminal element, all other will be generated as an array
 * => left element are generated as an associative array.
 * If the following character is ':' so the right element is a key named 'multiple:element_name'
 * If the following character is '->' so the right element will be named 'element_name'
 * Rule: If a key is named 'multiple:xxx' other key must be 'multiple:yyy'
 
   Docblock of  mock_function
   ---------------------------
   @ param array|struct $params
   @ subparam string $params:searches->search - the string to search
   @ subparam string $params:searches->search2 optional - optional string to search
   @ subparam string $params:searches->search3 - the string to search
   @ subparam string $params:airport->planes:plane->company->employees:employee->name - name of a employee of a company of a plane of an airport
   @ return array users
   @ subreturn integer $users:user->id
   @ subreturn integer $users:user->auth
 
   Generated description array
   ---------------------------
   description["mock_function"]=>
          array(3) {
            ["params"]=>
            array(2) {
              ["multiple:searches"]=>
              array(2) {
                ["search"]=>
                string(6) "string"
                ["search3"]=>
                string(6) "string"
              }
              ["multiple:airport"]=>
              array(1) {
                ["planes"]=>
                array(1) {
                  ["multiple:plane"]=>
                  array(1) {
                    ["company"]=>
                    array(1) {
                      ["employees"]=>
                      array(1) {
                        ["multiple:employee"]=>
                        array(1) {
                          ["name"]=>
                          string(6) "string"
                        }
                      }
                    }
                  }
                }
              }
            }
            ["optional"]=>
            array(1) {
              ["multiple:searches"]=>
              array(1) {
                ["search2"]=>
                string(6) "string"
              }
            }
            ["return"]=>
            array(1) {
              ["multiple:user"]=>
              array(13) {
                ["id"]=>
                string(7) "integer"
                ["auth"]=>
                string(7) "integer"
              }
            }
 */
 public static function generate_webservice_description($file, $class)
 {
     require_once $file;
     require_once "Zend/Loader.php";
     Zend_Loader::registerAutoload();
     $reflection = Zend_Server_Reflection::reflectClass($class);
     $description = array();
     foreach ($reflection->getMethods() as $method) {
         $docBlock = $method->getDocComment();
         //retrieve the return and add it into the description if not array|object
         preg_match_all('/@return\\s+(\\w+)\\s+((?:\\$)?\\w+)/', $docBlock, $returnmatches);
         //retrieve the subparam and subreturn
         preg_match_all('/\\s*\\*\\s*@(subparam|subreturn)\\s+(\\w+)\\s+(\\$\\w+(?::\\w+|->\\w+)+)((?:\\s+(?:optional|required|multiple))*)/', $docBlock, $matches);
         /// process every @subparam and @subreturn line of the docblock
         for ($i = 0; $i < sizeof($matches[1]); $i++) {
             /// identify the description type of the docblock line: is it params, optional or return (first key of a description method array)
             switch ($matches[1][$i]) {
                 case "subparam":
                     if (strpos($matches[4][$i], "optional") !== false) {
                         $descriptiontype = "optional";
                     } else {
                         $descriptiontype = "params";
                     }
                     break;
                 case "subreturn":
                     $descriptiontype = "return";
                     break;
             }
             /// init description[method]
             if (empty($description[$method->getName()])) {
                 $description[$method->getName()] = array();
             }
             /// directly set description[method][return] if the return value is a primary type
             if (strpos($returnmatches[1][0], "object") === false && strpos($returnmatches[1][0], "array") === false) {
                 $description[$method->getName()]['return'] = array($returnmatches[2][0] => $returnmatches[1][0]);
             }
             ///algorythm parts
             ///1. We compare the string to the description array
             ///   When we find a attribut that is not in the description, we retrieve all the rest of the string
             ///2. We create the missing part of the description array, starting from the end of the rest of the string
             ///3. We add the missing part to the description array
             ///Part 1.
             /// extract the first part into $param (has to be $params in the case of @subparam, or anything in the case of $subreturn)
             /// extract the second part
             if (strpos($matches[3][$i], "->") === false || strpos($matches[3][$i], ":") !== false && strpos($matches[3][$i], ":") < strpos($matches[3][$i], "->")) {
                 $separator = ":";
                 $separatorsize = 1;
             } else {
                 $separator = "->";
                 $separatorsize = 2;
             }
             $param = substr($matches[3][$i], 1, strpos($matches[3][$i], $separator) - 1);
             //first element/part/array
             //for example for the line @subparam string $params:students->student->name
             //    @params is the first element/part/array of this docnlock line
             //    students is the second element/part/array
             //    ...
             //    name is the terminal element, this element will be generated as String here
             $otherparam = substr($matches[3][$i], strpos($matches[3][$i], $separator) + $separatorsize);
             //rest of the line
             $parsingdesc = $description[$method->getName()];
             //$pasingdesc is the current position of the algorythm into the description array
             //it is used to check if a element already exist into the description array
             if (!empty($parsingdesc) && array_key_exists($descriptiontype, $parsingdesc)) {
                 $parsingdesc = $parsingdesc[$descriptiontype];
             }
             $descriptionpath = array();
             //we save in this variable the description path (e.g all keys to go deep into the description array)
             //it will be used to know where to add a new part the description array
             $creationfinished = false;
             //it's used to stop the algorythm when we find a new element that we can add to the descripitoin
             unset($type);
             /// try to extract the other elements and add them to the descripition id there are not already in the description
             while (!$creationfinished && (strpos($otherparam, ":") || strpos($otherparam, "->"))) {
                 if (strpos($otherparam, "->") === false || strpos($otherparam, ":") !== false && strpos($otherparam, ":") < strpos($otherparam, "->")) {
                     $type = $separator;
                     $separator = ":";
                     $separatorsize = 1;
                 } else {
                     $type = $separator;
                     $separator = "->";
                     $separatorsize = 2;
                 }
                 $param = substr($otherparam, 0, strpos($otherparam, $separator));
                 $otherparam = substr($otherparam, strpos($otherparam, $separator) + $separatorsize);
                 if ($type == ":") {
                     /// this element is not already in the description array yet and it is a non associative array
                     /// we add it (and its sub structure) to the description array
                     if (!array_key_exists('multiple:' . $param, $parsingdesc)) {
                         $desctoadd = webservice_lib::create_end_of_descriptionline(":" . $param . $separator . $otherparam, $matches[2][$i]);
                         if (empty($descriptionpath)) {
                             if (empty($description[$method->getName()]) || !array_key_exists($descriptiontype, $description[$method->getName()])) {
                                 $desctoadd = array($descriptiontype => $desctoadd);
                             }
                             $paramtoadd = $descriptiontype;
                         } else {
                             $paramtoadd = 'multiple:' . $param;
                         }
                         webservice_lib::add_end_of_description($paramtoadd, $desctoadd, $description[$method->getName()], $descriptionpath);
                         $creationfinished = true;
                         // we do not want to keep going to parse this line,
                         // neither add again the terminal element of the line to the descripiton
                     } else {
                         if (empty($descriptionpath)) {
                             $descriptionpath[] = $descriptiontype;
                         }
                         $descriptionpath[] = 'multiple:' . $param;
                         $parsingdesc = $parsingdesc['multiple:' . $param];
                     }
                 } else {
                     /// this element is not in the description array yet and it is a associative array
                     /// we add it (and its sub structure) to the description array
                     if (!array_key_exists($param, $parsingdesc)) {
                         $desctoadd = webservice_lib::create_end_of_descriptionline("->" . $param . $separator . $otherparam, $matches[2][$i]);
                         if (empty($descriptionpath)) {
                             if (empty($description[$method->getName()]) || !array_key_exists($descriptiontype, $description[$method->getName()])) {
                                 $desctoadd = array($descriptiontype => $desctoadd);
                             }
                             $paramtoadd = $descriptiontype;
                         } else {
                             $paramtoadd = $param;
                         }
                         webservice_lib::add_end_of_description($paramtoadd, $desctoadd, $description[$method->getName()], $descriptionpath);
                         $creationfinished = true;
                         // we do not want to keep going to parse this line,
                         // neither add again the terminal element of the line to the descripiton
                     } else {
                         if (empty($descriptionpath)) {
                             $descriptionpath[] = $descriptiontype;
                         }
                         $descriptionpath[] = $param;
                         $parsingdesc = $parsingdesc[$param];
                     }
                 }
             }
             /// Add the "terminal" element of the line to the description array
             if (!$creationfinished) {
                 if (!empty($type) && $type == ":") {
                     $desctoadd = webservice_lib::create_end_of_descriptionline($separator . $otherparam, $matches[2][$i]);
                     if (empty($descriptionpath)) {
                         if (empty($description[$method->getName()]) || !array_key_exists($descriptiontype, $description[$method->getName()])) {
                             $desctoadd = array($descriptiontype => $desctoadd);
                         }
                         $paramtoadd = $descriptiontype;
                     } else {
                         $paramtoadd = 'multiple:' . $param;
                     }
                     webservice_lib::add_end_of_description($paramtoadd, $desctoadd, $description[$method->getName()], $descriptionpath);
                 } else {
                     $desctoadd = webservice_lib::create_end_of_descriptionline($separator . $otherparam, $matches[2][$i]);
                     if (empty($descriptionpath)) {
                         if (empty($description[$method->getName()]) || !array_key_exists($descriptiontype, $description[$method->getName()])) {
                             $desctoadd = array($descriptiontype => $desctoadd);
                         }
                         $paramtoadd = $descriptiontype;
                     } else {
                         $paramtoadd = $param;
                     }
                     webservice_lib::add_end_of_description($paramtoadd, $desctoadd, $description[$method->getName()], $descriptionpath);
                 }
             }
         }
     }
     //                echo "<pre>";
     //                var_dump($description);
     //                echo "</pre>";
     return $description;
 }
Example #16
0
 /**
  * Attach class methods as XMLRPC method handlers
  *
  * $class may be either a class name or an object. Reflection is done on the
  * class or object to determine the available public methods, and each is
  * attached to the server as an available method; if a $namespace has been
  * provided, that namespace is used to prefix the XMLRPC method names.
  *
  * Any additional arguments beyond $namespace will be passed to a method at
  * invocation.
  *
  * @param string|object $class
  * @param string $namespace Optional
  * @param mixed $argv Optional arguments to pass to methods
  * @return void
  * @throws Zend_XmlRpc_Server_Exception on invalid input
  */
 public function setClass($class, $namespace = '', $argv = null)
 {
     if (is_string($class) && !class_exists($class)) {
         //require_once 'Zend/XmlRpc/Server/Exception.php';
         throw new Zend_XmlRpc_Server_Exception('Invalid method class', 610);
     }
     $args = null;
     if (2 < func_num_args()) {
         $args = func_get_args();
         $args = array_slice($args, 2);
     }
     $dispatchable = Zend_Server_Reflection::reflectClass($class, $args, $namespace);
     foreach ($dispatchable->getMethods() as $reflection) {
         $this->_buildSignature($reflection, $class);
     }
 }